Skip to content

Commit 8218435

Browse files
vtjnashKristofferC
authored andcommitted
inference: revisit all methods in cycle (#59974)
When encountering complicated cycles within cycles, make sure to revisit all applicable methods explicitly, since not all methods within the cycle will necessarily change return type after resolving the cycle. This shows up as the possibility of frames that don't get revisited before being cached, probably just caching `Union{}` as the call type instead. I always assumed this code was probably wrong, but didn't have any way to construct the counter-example to have confidence that fixing it would not cause some other side-effect. But still keep the backedge work lazy, since we don't want to allocate unnecessarily for a rarely used feature (recursion). Fix #59943 (cherry picked from commit f4847bf)
1 parent eda6a12 commit 8218435

File tree

1 file changed

+5
-12
lines changed

1 file changed

+5
-12
lines changed

Compiler/src/typeinfer.jl

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -761,17 +761,10 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState)
761761
end
762762

763763
function merge_call_chain!(::AbstractInterpreter, parent::InferenceState, child::InferenceState)
764-
# add backedge of parent <- child
765-
# then add all backedges of parent <- parent.parent
764+
# update all cycleid to be in the same group
766765
frames = parent.callstack::Vector{AbsIntState}
767766
@assert child.callstack === frames
768767
ancestorid = child.cycleid
769-
while true
770-
add_cycle_backedge!(parent, child)
771-
parent.cycleid === ancestorid && break
772-
child = parent
773-
parent = cycle_parent(child)::InferenceState
774-
end
775768
# ensure that walking the callstack has the same cycleid (DAG)
776769
for frameid = reverse(ancestorid:length(frames))
777770
frame = frames[frameid]::InferenceState
@@ -782,7 +775,6 @@ function merge_call_chain!(::AbstractInterpreter, parent::InferenceState, child:
782775
end
783776

784777
function add_cycle_backedge!(caller::InferenceState, frame::InferenceState)
785-
update_valid_age!(caller, frame.world.valid_worlds)
786778
backedge = (caller, caller.currpc)
787779
contains_is(frame.cycle_backedges, backedge) || push!(frame.cycle_backedges, backedge)
788780
return frame
@@ -801,9 +793,8 @@ end
801793
# frame matching `mi` is encountered, then there is a cycle in the call graph
802794
# (i.e. `mi` is a descendant callee of itself). Upon encountering this cycle,
803795
# we "resolve" it by merging the call chain, which entails updating each intermediary
804-
# frame's `cycleid` field and adding the appropriate backedges. Finally,
805-
# we return `mi`'s pre-existing frame. If no cycles are found, `nothing` is
806-
# returned instead.
796+
# frame's `cycleid` field. Finally, we return `mi`'s pre-existing frame.
797+
# If no cycles are found, `nothing` is returned instead.
807798
function resolve_call_cycle!(interp::AbstractInterpreter, mi::MethodInstance, parent::AbsIntState)
808799
# TODO (#48913) implement a proper recursion handling for irinterp:
809800
# This works most of the time currently just because the irinterp code doesn't get used much with
@@ -992,6 +983,7 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize
992983
result.ci_as_edge = edge_ci # set the edge for the inliner usage
993984
VolatileInferenceResult(result)
994985
end
986+
isinferred || add_cycle_backedge!(caller, frame)
995987
mresult[] = MethodCallResult(interp, caller, method, bestguess, exc_bestguess, effects,
996988
edge, edgecycle, edgelimited, volatile_inf_result)
997989
return true
@@ -1010,6 +1002,7 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize
10101002
update_valid_age!(caller, valid_worlds)
10111003
bestguess = frame.bestguess
10121004
exc_bestguess = refine_exception_type(frame.exc_bestguess, effects)
1005+
add_cycle_backedge!(caller, frame)
10131006
return Future(MethodCallResult(interp, caller, method, bestguess, exc_bestguess, effects, nothing, edgecycle, edgelimited))
10141007
end
10151008

0 commit comments

Comments
 (0)