Skip to content

Commit 551e0ea

Browse files
committed
Fix implementation for OpaqueClosure
1 parent 57fbef2 commit 551e0ea

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

stdlib/InteractiveUtils/src/macros.jl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ function construct_callable(@nospecialize(func::Type))
107107
# for callables such as `(::Returns{Int})(args...)` where using `Returns{Int}`
108108
# would give us code for the constructor, not for the callable object.
109109
throw(ArgumentError("If a function type is explicitly provided, it must be a singleton whose only instance is the callable object.
110-
To alleviate this restriction, the reflection macro may use `use_signature_tuple = true` from `gen_call_with_extracted_types`."))
110+
To alleviate this restriction, the reflection macro may set `use_signature_tuple = true` if using `gen_call_with_extracted_types`."))
111111
end
112112

113113
function separate_kwargs(exs::Vector{Any})
@@ -196,9 +196,21 @@ function merge_namedtuple_types(nt::Type{<:NamedTuple}, nts::Type{<:NamedTuple}.
196196
end
197197

198198
function gen_call(fcn, args, where_params, kws; use_signature_tuple::Bool)
199-
use_signature_tuple && return :($fcn($(esc(typesof_expr(args, where_params))); $(kws...)))
200199
f, args... = args
201-
return :($fcn($(esc(extract_farg(f))), $(esc(typesof_expr(args, where_params))); $(kws...)))
200+
args = collect(Any, args)
201+
!use_signature_tuple && return :($fcn($(esc(extract_farg(f))), $(esc(typesof_expr(args, where_params))); $(kws...)))
202+
# We use a signature tuple only if we are sure we won't get an opaque closure as first argument.
203+
# If we do get one, we have to use the 2-argument form.
204+
with_signature_tuple = :($fcn($(esc(typesof_expr(Any[f, args...], where_params))); $(kws...)))
205+
isexpr(f, :(::)) && return with_signature_tuple # we have a type, not a value, so not an OpaqueClosure
206+
return quote
207+
f = $(esc(f))
208+
if isa(f, Core.OpaqueClosure)
209+
$fcn(f, $(esc(typesof_expr(args, where_params))); $(kws...))
210+
else
211+
$with_signature_tuple
212+
end
213+
end
202214
end
203215

204216
is_code_macro(fcn) = startswith(string(fcn), "code_")

stdlib/InteractiveUtils/test/runtests.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,27 @@ end
398398
@test (@code_typed (::Base.Fix2{typeof(+), Float64})(3))[2] == Float64
399399
@test (@code_typed optimize=false (::Returns{Float64})(::Int64; name::String))[2] == Float64
400400
end
401+
402+
@testset "Opaque closures" begin
403+
opaque_f(@nospecialize(x::Type), @nospecialize(y::Type)) = sizeof(x) == sizeof(y)
404+
src, _ = only(code_typed(opaque_f, (Type, Type)))
405+
src.slottypes[1] = Tuple{}
406+
407+
# from CodeInfo
408+
oc = Core.OpaqueClosure(src; sig = Tuple{Type, Type}, rettype = Bool, nargs = 2)
409+
ret = @code_typed oc(Int64, Float64)
410+
@test [ret] == code_typed(oc)
411+
_, rt = ret
412+
@test rt === Bool
413+
414+
# from optimized IR
415+
ir = Core.Compiler.inflate_ir(src)
416+
oc = Core.OpaqueClosure(ir)
417+
ret = @code_typed oc(Int64, Float64)
418+
@test [ret] == code_typed(oc)
419+
_, rt = ret
420+
@test rt === Bool
421+
end
401422
end
402423

403424
module MacroTest

0 commit comments

Comments
 (0)