Skip to content

Commit f86b4ef

Browse files
authored
fix #44732, propagate effects of a thrown concrete call correctly (#44762)
1 parent c919811 commit f86b4ef

File tree

4 files changed

+43
-23
lines changed

4 files changed

+43
-23
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
136136
end
137137
tristate_merge!(sv, effects)
138138
push!(const_results, const_result)
139-
if const_result !== nothing
140-
any_const_result = true
141-
end
139+
any_const_result |= const_result !== nothing
142140
this_rt = tmerge(this_rt, rt)
143141
if bail_out_call(interp, this_rt, sv)
144142
break
@@ -187,9 +185,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
187185
end
188186
tristate_merge!(sv, effects)
189187
push!(const_results, const_result)
190-
if const_result !== nothing
191-
any_const_result = true
192-
end
188+
any_const_result |= const_result !== nothing
193189
end
194190
@assert !(this_conditional isa Conditional) "invalid lattice element returned from inter-procedural context"
195191
seen += 1
@@ -704,12 +700,12 @@ function pure_eval_call(interp::AbstractInterpreter,
704700
end
705701
function _pure_eval_call(@nospecialize(f), arginfo::ArgInfo)
706702
args = collect_const_args(arginfo)
707-
try
708-
value = Core._apply_pure(f, args)
709-
return Const(value)
703+
value = try
704+
Core._apply_pure(f, args)
710705
catch
711706
return nothing
712707
end
708+
return Const(value)
713709
end
714710

715711
function concrete_eval_eligible(interp::AbstractInterpreter,
@@ -743,17 +739,18 @@ function concrete_eval_call(interp::AbstractInterpreter,
743739
@nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState)
744740
concrete_eval_eligible(interp, f, result, arginfo, sv) || return nothing
745741
args = collect_const_args(arginfo)
746-
try
747-
value = Core._call_in_world_total(get_world_counter(interp), f, args...)
748-
if is_inlineable_constant(value) || call_result_unused(sv)
749-
# If the constant is not inlineable, still do the const-prop, since the
750-
# code that led to the creation of the Const may be inlineable in the same
751-
# circumstance and may be optimizable.
752-
return ConstCallResults(Const(value), ConstResult(result.edge, value), EFFECTS_TOTAL)
753-
end
742+
world = get_world_counter(interp)
743+
value = try
744+
Core._call_in_world_total(world, f, args...)
754745
catch
755746
# The evaulation threw. By :consistent-cy, we're guaranteed this would have happened at runtime
756-
return ConstCallResults(Union{}, ConstResult(result.edge), result.edge_effects)
747+
return ConstCallResults(Union{}, ConstResult(result.edge, result.edge_effects), result.edge_effects)
748+
end
749+
if is_inlineable_constant(value) || call_result_unused(sv)
750+
# If the constant is not inlineable, still do the const-prop, since the
751+
# code that led to the creation of the Const may be inlineable in the same
752+
# circumstance and may be optimizable.
753+
return ConstCallResults(Const(value), ConstResult(result.edge, EFFECTS_TOTAL, value), EFFECTS_TOTAL)
757754
end
758755
return nothing
759756
end

base/compiler/ssair/inlining.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,10 +1330,10 @@ end
13301330

13311331
function const_result_item(result::ConstResult, state::InliningState)
13321332
if !isdefined(result, :result) || !is_inlineable_constant(result.result)
1333-
return compileable_specialization(state.et, result.mi, EFFECTS_TOTAL)
1334-
else
1335-
return ConstantCase(quoted(result.result))
1333+
return compileable_specialization(state.et, result.mi, result.effects)
13361334
end
1335+
@assert result.effects === EFFECTS_TOTAL
1336+
return ConstantCase(quoted(result.result))
13371337
end
13381338

13391339
function handle_cases!(ir::IRCode, idx::Int, stmt::Expr, @nospecialize(atype),

base/compiler/stmtinfo.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ end
4949

5050
struct ConstResult
5151
mi::MethodInstance
52+
effects::Effects
5253
result
53-
ConstResult(mi::MethodInstance) = new(mi)
54-
ConstResult(mi::MethodInstance, @nospecialize val) = new(mi, val)
54+
ConstResult(mi::MethodInstance, effects::Effects) = new(mi, effects)
55+
ConstResult(mi::MethodInstance, effects::Effects, @nospecialize val) = new(mi, effects, val)
5556
end
5657

5758
"""

test/compiler/inline.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,28 @@ Base.@assume_effects :consistent :effect_free :terminates_globally consteval(
10951095
consteval(getindex, ___CONST_DICT___, :a)
10961096
end
10971097

1098+
# https://github.com/JuliaLang/julia/issues/44732
1099+
struct Component44732
1100+
v
1101+
end
1102+
struct Container44732
1103+
x::Union{Nothing,Component44732}
1104+
end
1105+
1106+
# NOTE make sure to prevent inference bail out
1107+
validate44732(::Component44732) = nothing
1108+
validate44732(::Any) = error("don't erase this error!")
1109+
1110+
function issue44732(c::Container44732)
1111+
validate44732(c.x)
1112+
return nothing
1113+
end
1114+
1115+
let src = code_typed1(issue44732, (Container44732,))
1116+
@test any(isinvoke(:validate44732), src.code)
1117+
end
1118+
@test_throws ErrorException("don't erase this error!") issue44732(Container44732(nothing))
1119+
10981120
global x44200::Int = 0
10991121
function f44200()
11001122
global x = 0

0 commit comments

Comments
 (0)