diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index f1f6e78e241f62..966e0ee54be5e3 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1253,6 +1253,9 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), return abstract_modifyfield!(interp, argtypes, sv) end return CallMeta(abstract_call_builtin(interp, f, fargs, argtypes, sv, max_methods), false) + elseif isa(f, Core.OpaqueClosure) + # calling an OpaqueClosure about which we have no information returns no information + return CallMeta(Any, false) elseif f === Core.kwfunc if la == 2 aty = argtypes[2] @@ -1380,8 +1383,8 @@ function abstract_call(interp::AbstractInterpreter, fargs::Union{Nothing,Vector{ f = argtype_to_function(ft) if isa(ft, PartialOpaque) return abstract_call_opaque_closure(interp, ft, argtypes[2:end], sv) - elseif (uft = unwrap_unionall(ft); isa(uft, DataType) && uft.name === typename(Core.OpaqueClosure)) - return CallMeta(rewrap_unionall((uft::DataType).parameters[2], ft), false) + elseif (uft = unwrap_unionall(widenconst(ft)); isa(uft, DataType) && uft.name === typename(Core.OpaqueClosure)) + return CallMeta(rewrap_unionall((uft::DataType).parameters[2], widenconst(ft)), false) elseif f === nothing # non-constant function, but the number of arguments is known # and the ft is not a Builtin or IntrinsicFunction diff --git a/test/opaque_closure.jl b/test/opaque_closure.jl index 796aac7072c605..e416f96230a6e2 100644 --- a/test/opaque_closure.jl +++ b/test/opaque_closure.jl @@ -206,3 +206,8 @@ end @test f_oc_noinline_call(1, 2) == 3 @test_throws MethodError (@opaque x->x+1)(1, 2) + +# https://github.com/JuliaLang/julia/issues/40409 +const GLOBAL_OPAQUE_CLOSURE = @opaque () -> 123 +call_global_opaque_closure() = GLOBAL_OPAQUE_CLOSURE() +@test call_global_opaque_closure() == 123