diff --git a/base/errorshow.jl b/base/errorshow.jl index e56a095d832fd..2f6fa6604b775 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -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) diff --git a/base/methodshow.jl b/base/methodshow.jl index ba9911179fd19..2688434423f30 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -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) diff --git a/src/method.c b/src/method.c index 48efa04d59e40..6dd9546a8dde0 100644 --- a/src/method.c +++ b/src/method.c @@ -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; } diff --git a/test/opaque_closure.jl b/test/opaque_closure.jl index 0e2ce5f794605..981baf0158bbd 100644 --- a/test/opaque_closure.jl +++ b/test/opaque_closure.jl @@ -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