diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 3e34528aa8284..eae484b739ad9 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1503,25 +1503,26 @@ end function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, sv::InferenceState) ft′ = argtype_by_index(argtypes, 2) ft = widenconst(ft′) - ft === Bottom && return CallMeta(Bottom, false) + ft === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWN (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3)) - types === Bottom && return CallMeta(Bottom, false) - isexact || return CallMeta(Any, false) + types === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWN + isexact || return CallMeta(Any, false), Effects() argtype = argtypes_to_type(argtype_tail(argtypes, 4)) nargtype = typeintersect(types, argtype) - nargtype === Bottom && return CallMeta(Bottom, false) - nargtype isa DataType || return CallMeta(Any, false) # other cases are not implemented below - isdispatchelem(ft) || return CallMeta(Any, false) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below + nargtype === Bottom && return CallMeta(Bottom, false), EFFECTS_THROWN + nargtype isa DataType || return CallMeta(Any, false), Effects() # other cases are not implemented below + isdispatchelem(ft) || return CallMeta(Any, false), Effects() # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below ft = ft::DataType types = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type nargtype = Tuple{ft, nargtype.parameters...} argtype = Tuple{ft, argtype.parameters...} match, valid_worlds, overlayed = findsup(types, method_table(interp)) - match === nothing && return CallMeta(Any, false) + match === nothing && return CallMeta(Any, false), Effects() update_valid_age!(sv, valid_worlds) method = match.method (ti, env::SimpleVector) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector (; rt, edge) = result = abstract_call_method(interp, method, ti, env, false, sv) + effects = result.edge_effects edge !== nothing && add_backedge!(edge::MethodInstance, sv) match = MethodMatch(ti, env, method, argtype <: method.sig) res = nothing @@ -1539,10 +1540,10 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn const_result = nothing if const_call_result !== nothing if const_call_result.rt ⊑ rt - (; rt, const_result) = const_call_result + (; rt, effects, const_result) = const_call_result end end - return CallMeta(from_interprocedural!(rt, sv, arginfo, sig), InvokeCallInfo(match, const_result)) + return CallMeta(from_interprocedural!(rt, sv, arginfo, sig), InvokeCallInfo(match, const_result)), effects end function invoke_rewrite(xs::Vector{Any}) @@ -1563,14 +1564,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), if f === _apply_iterate return abstract_apply(interp, argtypes, sv, max_methods) elseif f === invoke - call = abstract_invoke(interp, arginfo, sv) - if call.info === false - if call.rt === Bottom - tristate_merge!(sv, Effects(EFFECTS_TOTAL; nothrow=ALWAYS_FALSE)) - else - tristate_merge!(sv, Effects()) - end - end + call, effects = abstract_invoke(interp, arginfo, sv) + tristate_merge!(sv, effects) return call elseif f === modifyfield! tristate_merge!(sv, Effects()) # TODO diff --git a/base/compiler/types.jl b/base/compiler/types.jl index eff601dd7dc6e..0d8275ac0e7a0 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -59,6 +59,7 @@ function Effects( end const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, false) +const EFFECTS_THROWN = Effects(ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_FALSE, ALWAYS_TRUE, false) const EFFECTS_UNKNOWN = Effects(TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, true) function Effects(e::Effects = EFFECTS_UNKNOWN; diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 955dafeca4b7f..4b928d4f648e1 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -4080,3 +4080,12 @@ end Base.Experimental.@force_compile Core.Compiler.return_type(+, NTuple{2, Rational}) end == Rational + +# https://github.com/JuliaLang/julia/issues/44763 +global x44763::Int = 0 +increase_x44763!(n) = (global x44763; x44763 += n) +invoke44763(x) = Base.@invoke increase_x44763!(x) +@test Base.return_types() do + invoke44763(42) +end |> only === Int +@test x44763 == 0