@@ -63,6 +63,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
63
63
nonbot = 0 # the index of the only non-Bottom inference result if > 0
64
64
seen = 0 # number of signatures actually inferred
65
65
istoplevel = sv. linfo. def isa Module
66
+ any_splitunions = napplicable > 1
66
67
for i in 1 : napplicable
67
68
match = applicable[i]:: SimpleVector
68
69
method = match[3 ]:: Method
@@ -80,7 +81,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
80
81
if splitunions
81
82
splitsigs = switchtupleunion (sig)
82
83
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 (), any_splitunions, sv)
84
85
if edge != = nothing
85
86
push! (edges, edge)
86
87
end
@@ -89,7 +90,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
89
90
this_rt === Any && break
90
91
end
91
92
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 , any_splitunions, sv)
93
94
edgecycle |= edgecycle1:: Bool
94
95
if edge != = nothing
95
96
push! (edges, edge)
@@ -227,7 +228,7 @@ function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecial
227
228
return result
228
229
end
229
230
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 )
231
232
if method. name === :depwarn && isdefined (Main, :Base ) && method. module === Main. Base
232
233
return Any, false , nothing
233
234
end
@@ -266,30 +267,36 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl
266
267
inf_method2 = infstate. src. method_for_inference_limit_heuristics # limit only if user token match
267
268
inf_method2 isa Method || (inf_method2 = nothing ) # Union{Method, Nothing}
268
269
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
288
282
parent_method2 = parent. src. method_for_inference_limit_heuristics # limit only if user token match
289
283
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
291
285
topmost = infstate
292
286
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
293
300
end
294
301
end
295
302
end
@@ -321,7 +328,7 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl
321
328
comparison = method. sig
322
329
end
323
330
# 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)
325
332
326
333
if newsig != = sig
327
334
# continue inference, but note that we've limited parameter complexity
0 commit comments