Skip to content

Commit b1ca583

Browse files
committed
add versions of code_typed and which that accept tuple types
1 parent be72a57 commit b1ca583

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

base/reflection.jl

+38-4
Original file line numberDiff line numberDiff line change
@@ -1081,10 +1081,31 @@ function code_typed(@nospecialize(f), @nospecialize(types=Tuple);
10811081
debuginfo::Symbol=:default,
10821082
world = get_world_counter(),
10831083
interp = Core.Compiler.NativeInterpreter(world))
1084-
ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
10851084
if isa(f, Core.Builtin)
10861085
throw(ArgumentError("argument is not a generic function"))
10871086
end
1087+
ft = Core.Typeof(f)
1088+
if isa(types, Type)
1089+
u = unwrap_unionall(types)
1090+
tt = rewrap_unionall(Tuple{ft, u.parameters...}, types)
1091+
else
1092+
tt = Tuple{ft, types...}
1093+
end
1094+
return code_typed_by_type(tt; optimize, debuginfo, world, interp)
1095+
end
1096+
1097+
"""
1098+
code_typed_by_type(types::Type{<:Tuple}; ...)
1099+
1100+
Similar to [`code_typed`](@ref), except the argument is a tuple type describing
1101+
a full signature to query.
1102+
"""
1103+
function code_typed_by_type(@nospecialize(tt::Type);
1104+
optimize=true,
1105+
debuginfo::Symbol=:default,
1106+
world = get_world_counter(),
1107+
interp = Core.Compiler.NativeInterpreter(world))
1108+
ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
10881109
if @isdefined(IRShow)
10891110
debuginfo = IRShow.debuginfo(debuginfo)
10901111
elseif debuginfo === :default
@@ -1093,10 +1114,14 @@ function code_typed(@nospecialize(f), @nospecialize(types=Tuple);
10931114
if debuginfo !== :source && debuginfo !== :none
10941115
throw(ArgumentError("'debuginfo' must be either :source or :none"))
10951116
end
1096-
types = to_tuple_type(types)
1117+
tt = to_tuple_type(tt)
1118+
meths = _methods_by_ftype(tt, -1, world)
1119+
if meths === false
1120+
error("signature does not correspond to a generic function")
1121+
end
10971122
asts = []
1098-
for x in _methods(f, types, -1, world)
1099-
meth = func_for_method_checked(x[3], types, x[2])
1123+
for x in meths
1124+
meth = func_for_method_checked(x[3], tt, x[2])
11001125
(code, ty) = Core.Compiler.typeinf_code(interp, meth, x[1], x[2], optimize)
11011126
code === nothing && error("inference not successful") # inference disabled?
11021127
debuginfo === :none && remove_linenums!(code)
@@ -1135,6 +1160,15 @@ function which(@nospecialize(f), @nospecialize(t))
11351160
end
11361161
t = to_tuple_type(t)
11371162
tt = signature_type(f, t)
1163+
return which(tt)
1164+
end
1165+
1166+
"""
1167+
which(types::Type{<:Tuple})
1168+
1169+
Returns the method that would be called by the given type signature (as a tuple type).
1170+
"""
1171+
function which(@nospecialize(tt::Type))
11381172
m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tt, typemax(UInt))
11391173
if m === nothing
11401174
error("no unique matching method found for the specified argument types")

test/reflection.jl

+6
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@ let
525525
@test !isdefined(mi.cache, :next)
526526
end
527527

528+
# code_typed_by_type
529+
@test Base.code_typed_by_type(Tuple{Type{<:Val}})[1][2] == Val
530+
@test Base.code_typed_by_type(Tuple{typeof(sin), Float64})[1][2] === Float64
531+
@test_throws ErrorException("signature does not correspond to a generic function") Base.code_typed_by_type(Tuple{Any})
532+
528533
# New reflection methods in 0.6
529534
struct ReflectionExample{T<:AbstractFloat, N}
530535
x::Tuple{T, N}
@@ -820,6 +825,7 @@ f20872(::Val, ::Val) = false
820825
@test which(f20872, Tuple{Val,Val}).sig == Tuple{typeof(f20872), Val, Val}
821826
@test which(f20872, Tuple{Val,Val{N}} where N).sig == Tuple{typeof(f20872), Val, Val}
822827
@test_throws ErrorException which(f20872, Tuple{Any,Val{N}} where N)
828+
@test which(Tuple{typeof(f20872), Val{1}, Val{2}}).sig == Tuple{typeof(f20872), Val, Val}
823829

824830
module M29962 end
825831
# make sure checking if a binding is deprecated does not resolve it

0 commit comments

Comments
 (0)