Skip to content

Commit

Permalink
fixes to OpaqueClosure argument count handling and MethodError display
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Apr 8, 2022
1 parent c5fae67 commit 79a1c42
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 14 deletions.
6 changes: 5 additions & 1 deletion base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
buf = IOBuffer()
iob0 = iob = IOContext(buf, io)
tv = Any[]
sig0 = method.sig
if func isa Core.OpaqueClosure
sig0 = signature_type(func, typeof(func).parameters[1])
else
sig0 = method.sig
end
while isa(sig0, UnionAll)
push!(tv, sig0.var)
iob = IOContext(iob, :unionall_env => sig0.var)
Expand Down
3 changes: 3 additions & 0 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ end

# NOTE: second argument is deprecated and is no longer used
function kwarg_decl(m::Method, kwtype = nothing)
if m.sig === Tuple # OpaqueClosure
return Symbol[]
end
mt = get_methodtable(m)
if isdefined(mt, :kwsorter)
kwtype = typeof(mt.kwsorter)
Expand Down
13 changes: 8 additions & 5 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_sve
return jl_module_globalref(module, (jl_sym_t*)expr);
}
else if (jl_is_returnnode(expr)) {
jl_value_t *val = resolve_globals(jl_returnnode_value(expr), module, sparam_vals, binding_effects, eager_resolve);
if (val != jl_returnnode_value(expr)) {
JL_GC_PUSH1(&val);
expr = jl_new_struct(jl_returnnode_type, val);
JL_GC_POP();
jl_value_t *retval = jl_returnnode_value(expr);
if (retval) {
jl_value_t *val = resolve_globals(retval, module, sparam_vals, binding_effects, eager_resolve);
if (val != retval) {
JL_GC_PUSH1(&val);
expr = jl_new_struct(jl_returnnode_type, val);
JL_GC_POP();
}
}
return expr;
}
Expand Down
36 changes: 28 additions & 8 deletions test/opaque_closure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -244,21 +244,41 @@ end
using Core.Compiler: IRCode
using Core: CodeInfo

function OC(ir::IRCode, env...)
src = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ());
function OC(ir::IRCode, nargs::Int, isva::Bool, env...)
if (isva && nargs > length(ir.argtypes)) || (!isva && nargs != length(ir.argtypes))
throw(ArgumentError("invalid argument count"))
end
src = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ())
src.slotflags = UInt8[]
nargs = length(ir.argtypes)
src.slotnames = fill(:none, nargs)
Core.Compiler.replace_code_newstyle!(src, ir, nargs);
Core.Compiler.widen_all_consts!(src);
src.slotnames = fill(:none, nargs+1)
Core.Compiler.replace_code_newstyle!(src, ir, nargs+1)
Core.Compiler.widen_all_consts!(src)
src.inferred = true
# NOTE: we need ir.argtypes[1] == typeof(env)

ccall(:jl_new_opaque_closure_from_code_info, Any, (Any, Any, Any, Any, Any, Cint, Any, Cint, Cint, Any),
Tuple{ir.argtypes[2:end]...}, Union{}, Any, @__MODULE__, src, 0, nothing, nargs-1, false, env)
Tuple{ir.argtypes[2:end]...}, Union{}, Any, @__MODULE__, src, 0, nothing, nargs, isva, env)
end

function OC(src::CodeInfo, env...)
M = src.parent.def
sig = Base.tuple_type_tail(src.parent.specTypes)

ccall(:jl_new_opaque_closure_from_code_info, Any, (Any, Any, Any, Any, Any, Cint, Any, Cint, Cint, Any),
sig, Union{}, Any, @__MODULE__, src, 0, nothing, M.nargs - 1, M.isva, env)
end

let ci = code_typed(+, (Int, Int))[1][1]
ir = Core.Compiler.inflate_ir(ci)
@test OC(ir)(40, 2) == 42
@test OC(ir, 2, false)(40, 2) == 42
end

let ci = code_typed((x, y...)->(x, y), (Int, Int))[1][1]
ir = Core.Compiler.inflate_ir(ci)
@test OC(ir, 2, true)(40, 2) === (40, (2,))
end

let ci = code_typed((x, y...)->(x, y), (Int, Int))[1][1]
@test OC(ci)(1, 2) === (1, (2,))
@test_throws MethodError OC(ci)(1, 2, 3)
end

0 comments on commit 79a1c42

Please sign in to comment.