Skip to content

Commit 142f419

Browse files
authored
InteractiveUtils: support syntax found in stacktraces for introspection macros (#58222)
Continuing the work done at #57909, this PR adds support for the following syntax: ```julia @code_typed f(some_undef_var::Int) # some_undef_var is ignored, only the annotation is used @code_typed f(; x::Int) # same here, the name is used but not the value ``` This should allow us to copy and paste signatures found in stacktraces, such as ```julia julia> f(x; y = 3) = error() f (generic function with 1 method) julia> f(1) ERROR: Stacktrace: [1] error() @ Base ./error.jl:45 [2] f(x::Int64; y::Int64) @ Main ./REPL[40]:1 [3] top-level scope @ REPL[41]:1 julia> asin(-2) ERROR: DomainError with -2.0: asin(x) is not defined for |x| > 1. Stacktrace: [1] asin_domain_error(x::Float64) @ Base.Math ./special/trig.jl:429 [2] asin(x::Float64) @ Base.Math ./special/trig.jl:443 ``` where any function call may be copied and pasted into `@code_typed`, `@edit` etc as is, provided that the function and argument types are defined in the active module (i.e. `Main`). Thanks @topolarity for the idea. --------- Co-authored-by: Cédric Belmant <[email protected]>
1 parent b4c12f4 commit 142f419

File tree

3 files changed

+8
-1
lines changed

3 files changed

+8
-1
lines changed

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Standard library changes
4949

5050
#### InteractiveUtils
5151

52-
* Introspection utilities such as `@code_typed`, `@which` and `@edit` now accept type annotations as substitutes for values, recognizing forms such as `f(1, ::Float64, 3)` or even `sum(::Vector{T}; init = ::T) where {T<:Real}` ([#57909]).
52+
* Introspection utilities such as `@code_typed`, `@which` and `@edit` now accept type annotations as substitutes for values, recognizing forms such as `f(1, ::Float64, 3)` or even `sum(::Vector{T}; init = ::T) where {T<:Real}`. Type-annotated variables as in `f(val::Int; kw::Float64)` are not evaluated if the type annotation provides the necessary information, making this syntax compatible with signatures found in stacktraces ([#57909], [#58222]).
5353

5454
External dependencies
5555
---------------------

stdlib/InteractiveUtils/src/macros.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ end
2323

2424
function get_typeof(@nospecialize ex)
2525
isexpr(ex, :(::), 1) && return esc(ex.args[1])
26+
isexpr(ex, :(::), 2) && return esc(ex.args[2])
2627
if isexpr(ex, :..., 1)
2728
splatted = ex.args[1]
2829
isexpr(splatted, :(::), 1) && return Expr(:curly, :Vararg, esc(splatted.args[1]))
@@ -93,6 +94,7 @@ function are_kwargs_valid(kwargs::Vector{Any})
9394
for kwarg in kwargs
9495
isexpr(kwarg, :..., 1) && continue
9596
isexpr(kwarg, :kw, 2) && isa(kwarg.args[1], Symbol) && continue
97+
isexpr(kwarg, :(::), 2) && continue
9698
isa(kwarg, Symbol) && continue
9799
return false
98100
end
@@ -113,6 +115,8 @@ function generate_merged_namedtuple_type(kwargs::Vector{Any})
113115
push!(nts, Expr(:call, typeof_nt, esc(ex.args[1])))
114116
elseif isexpr(ex, :kw, 2)
115117
push!(ntargs, ex.args[1]::Symbol => get_typeof(ex.args[2]))
118+
elseif isexpr(ex, :(::), 2)
119+
push!(ntargs, ex.args[1]::Symbol => get_typeof(ex))
116120
else
117121
ex::Symbol
118122
push!(ntargs, ex => get_typeof(ex))

stdlib/InteractiveUtils/test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ end
337337
@test (@which (::Base.RefValue{Int}).x = ::Int).name === :setproperty!
338338
@test (@which (::Float64)^2).name === :literal_pow
339339
@test (@which [::Int]).name === :vect
340+
@test (@which [undef_var::Int]).name === :vect
340341
@test (@which [::Int 2]).name === :hcat
341342
@test (@which [::Int; 2]).name === :vcat
342343
@test (@which Int[::Int 2]).name === :typed_hcat
@@ -345,6 +346,7 @@ end
345346
@test (@which Int[::Int 2;3 (::Int)]).name === :typed_hvcat
346347
@test (@which (::Vector{Float64})').name === :adjoint
347348
@test (@which "$(::Symbol) is a symbol").sig === Tuple{typeof(string), Vararg{Union{Char, String, Symbol}}}
349+
@test (@which +(some_x::Int, some_y::Float64)).name === :+
348350
@test (@which +(::Any, ::Any, ::Any, ::Any...)).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}}
349351
@test (@which +(::Any, ::Any, ::Any, ::Vararg{Any})).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}}
350352
n = length(@code_typed +(::Float64, ::Vararg{Float64}))
@@ -358,6 +360,7 @@ end
358360
@test (@which +(::T, ::T) where {T<:Number}).sig === Tuple{typeof(+), T, T} where {T<:Number}
359361
@test (@which round(::Float64; digits=3)).name === :round
360362
@test (@which round(1.2; digits = ::Int)).name === :round
363+
@test (@which round(1.2; digits::Int)).name === :round
361364
@test (@code_typed round(::T; digits = ::T) where {T<:Float64})[2] === Union{}
362365
@test (@code_typed round(::T; digits = ::T) where {T<:Int})[2] === Float64
363366
base = 10

0 commit comments

Comments
 (0)