diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 1449b911ee629..0544340a1091a 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2089,6 +2089,19 @@ function abstract_eval_global(M::Module, s::Symbol, frame::InferenceState) return ty end +function abstract_eval_global_assignment(interp::AbstractInterpreter, frame::InferenceState, lhs::GlobalRef, @nospecialize(rhs)) + M = lhs.mod + s = lhs.name + nothrow = false + if isdefined(M, s) && !isconst(M, s) + ty = ccall(:jl_binding_type, Any, (Any, Any), M, s) + nothrow = ty === nothing || rhs ⊑ ty + end + tristate_merge!(frame, Effects(EFFECTS_TOTAL, + effect_free=TRISTATE_UNKNOWN, + nothrow=nothrow ? ALWAYS_TRUE : TRISTATE_UNKNOWN)) +end + abstract_eval_ssavalue(s::SSAValue, sv::InferenceState) = abstract_eval_ssavalue(s, sv.src) function abstract_eval_ssavalue(s::SSAValue, src::CodeInfo) typ = (src.ssavaluetypes::Vector{Any})[s.id] @@ -2321,9 +2334,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) if isa(lhs, SlotNumber) changes = StateUpdate(lhs, VarState(t, false), changes, false) elseif isa(lhs, GlobalRef) - tristate_merge!(frame, Effects(EFFECTS_TOTAL, - effect_free=TRISTATE_UNKNOWN, - nothrow=TRISTATE_UNKNOWN)) + abstract_eval_global_assignment(interp, frame, lhs, t) elseif !isa(lhs, SSAValue) tristate_merge!(frame, EFFECTS_UNKNOWN) end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 15307a64c355b..0c819a6bd4904 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -4133,3 +4133,11 @@ end |> !Core.Compiler.is_concrete_eval_eligible @test !fully_eliminated() do entry_to_be_invalidated('a') end + +# Nothrow for assignment to globals +global glob_assign_int::Int = 0 +f_glob_assign_int() = global glob_assign_int += 1 +let effects = Base.infer_effects(f_glob_assign_int, ()) + @test !Core.Compiler.is_effect_free(effects) + @test Core.Compiler.is_nothrow(effects) +end