@@ -63,6 +63,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
6363 nonbot = 0 # the index of the only non-Bottom inference result if > 0
6464 seen = 0 # number of signatures actually inferred
6565 istoplevel = sv. linfo. def isa Module
66+ multiple_matches = napplicable > 1
6667 for i in 1 : napplicable
6768 match = applicable[i]:: SimpleVector
6869 method = match[3 ]:: Method
@@ -80,7 +81,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
8081 if splitunions
8182 splitsigs = switchtupleunion (sig)
8283 for sig_n in splitsigs
83- rt, edgecycle1, edge = abstract_call_method (method, sig_n, svec (), sv)
84+ rt, edgecycle1, edge = abstract_call_method (method, sig_n, svec (), multiple_matches, sv)
8485 if edge != = nothing
8586 push! (edges, edge)
8687 end
@@ -89,7 +90,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
8990 this_rt === Any && break
9091 end
9192 else
92- this_rt, edgecycle1, edge = abstract_call_method (method, sig, match[2 ]:: SimpleVector , sv)
93+ this_rt, edgecycle1, edge = abstract_call_method (method, sig, match[2 ]:: SimpleVector , multiple_matches, sv)
9394 edgecycle |= edgecycle1:: Bool
9495 if edge != = nothing
9596 push! (edges, edge)
@@ -227,7 +228,7 @@ function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecial
227228 return result
228229end
229230
230- function abstract_call_method (method:: Method , @nospecialize (sig), sparams:: SimpleVector , sv:: InferenceState )
231+ function abstract_call_method (method:: Method , @nospecialize (sig), sparams:: SimpleVector , hardlimit :: Bool , sv:: InferenceState )
231232 if method. name === :depwarn && isdefined (Main, :Base ) && method. module === Main. Base
232233 return Any, false , nothing
233234 end
@@ -266,30 +267,36 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl
266267 inf_method2 = infstate. src. method_for_inference_limit_heuristics # limit only if user token match
267268 inf_method2 isa Method || (inf_method2 = nothing ) # Union{Method, Nothing}
268269 if topmost === nothing && method2 === inf_method2
269- # inspect the parent of this edge,
270- # to see if they are the same Method as sv
271- # in which case we'll need to ensure it is convergent
272- # otherwise, we don't
273- for parent in infstate. callers_in_cycle
274- # check in the cycle list first
275- # all items in here are mutual parents of all others
276- parent_method2 = parent. src. method_for_inference_limit_heuristics # limit only if user token match
277- parent_method2 isa Method || (parent_method2 = nothing ) # Union{Method, Nothing}
278- if parent. linfo. def === sv. linfo. def && sv_method2 === parent_method2
279- topmost = infstate
280- edgecycle = true
281- break
282- end
283- end
284- let parent = infstate. parent
285- # then check the parent link
286- if topmost === nothing && parent != = nothing
287- parent = parent:: InferenceState
270+ if hardlimit
271+ topmost = infstate
272+ edgecycle = true
273+ else
274+ # if this is a soft limit,
275+ # also inspect the parent of this edge,
276+ # to see if they are the same Method as sv
277+ # in which case we'll need to ensure it is convergent
278+ # otherwise, we don't
279+ for parent in infstate. callers_in_cycle
280+ # check in the cycle list first
281+ # all items in here are mutual parents of all others
288282 parent_method2 = parent. src. method_for_inference_limit_heuristics # limit only if user token match
289283 parent_method2 isa Method || (parent_method2 = nothing ) # Union{Method, Nothing}
290- if (parent . cached || parent . limited) && parent. linfo. def === sv. linfo. def && sv_method2 === parent_method2
284+ if parent. linfo. def === sv. linfo. def && sv_method2 === parent_method2
291285 topmost = infstate
292286 edgecycle = true
287+ break
288+ end
289+ end
290+ let parent = infstate. parent
291+ # then check the parent link
292+ if topmost === nothing && parent != = nothing
293+ parent = parent:: InferenceState
294+ parent_method2 = parent. src. method_for_inference_limit_heuristics # limit only if user token match
295+ parent_method2 isa Method || (parent_method2 = nothing ) # Union{Method, Nothing}
296+ if (parent. cached || parent. limited) && parent. linfo. def === sv. linfo. def && sv_method2 === parent_method2
297+ topmost = infstate
298+ edgecycle = true
299+ end
293300 end
294301 end
295302 end
@@ -321,7 +328,7 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl
321328 comparison = method. sig
322329 end
323330 # see if the type is actually too big (relative to the caller), and limit it if required
324- newsig = limit_type_size (sig, comparison, sv. linfo. specTypes, sv. params. TUPLE_COMPLEXITY_LIMIT_DEPTH, spec_len)
331+ newsig = limit_type_size (sig, comparison, hardlimit ? comparison : sv. linfo. specTypes, sv. params. TUPLE_COMPLEXITY_LIMIT_DEPTH, spec_len)
325332
326333 if newsig != = sig
327334 # continue inference, but note that we've limited parameter complexity
0 commit comments