@@ -280,17 +280,41 @@ any_ambig(info::MethodMatchInfo) = any_ambig(info.results)
280
280
any_ambig (m:: MethodMatches ) = any_ambig (m. info)
281
281
fully_covering (info:: MethodMatchInfo ) = info. fullmatch
282
282
fully_covering (m:: MethodMatches ) = fully_covering (m. info)
283
+ function add_uncovered_edges! (sv:: AbsIntState , info:: MethodMatchInfo , @nospecialize (atype))
284
+ fully_covering (info) || add_mt_backedge! (sv, info. mt, atype)
285
+ nothing
286
+ end
287
+ add_uncovered_edges! (sv:: AbsIntState , matches:: MethodMatches , @nospecialize (atype)) =
288
+ add_uncovered_edges! (sv, matches. info, atype)
283
289
284
290
struct UnionSplitMethodMatches
285
291
applicable:: Vector{Any}
286
292
applicable_argtypes:: Vector{Vector{Any}}
287
293
info:: UnionSplitInfo
288
294
valid_worlds:: WorldRange
289
295
end
290
- any_ambig (info:: UnionSplitInfo ) = any (any_ambig, info. matches )
296
+ any_ambig (info:: UnionSplitInfo ) = any (any_ambig, info. split )
291
297
any_ambig (m:: UnionSplitMethodMatches ) = any_ambig (m. info)
292
- fully_covering (info:: UnionSplitInfo ) = all (info. fullmatches )
298
+ fully_covering (info:: UnionSplitInfo ) = all (fully_covering, info. split )
293
299
fully_covering (m:: UnionSplitMethodMatches ) = fully_covering (m. info)
300
+ function add_uncovered_edges! (sv:: AbsIntState , info:: UnionSplitInfo , @nospecialize (atype))
301
+ all (fully_covering, info. split) && return nothing
302
+ # add mt backedges with removing duplications
303
+ for mt in uncovered_method_tables (info)
304
+ add_mt_backedge! (sv, mt, atype)
305
+ end
306
+ end
307
+ add_uncovered_edges! (sv:: AbsIntState , matches:: UnionSplitMethodMatches , @nospecialize (atype)) =
308
+ add_uncovered_edges! (sv, matches. info, atype)
309
+ function uncovered_method_tables (info:: UnionSplitInfo )
310
+ mts = MethodTable[]
311
+ for mminfo in info. split
312
+ fully_covering (mminfo) && continue
313
+ any (mt′:: MethodTable -> mt′=== mminfo. mt, mts) && continue
314
+ push! (mts, mminfo. mt)
315
+ end
316
+ return mts
317
+ end
294
318
295
319
function find_method_matches (interp:: AbstractInterpreter , argtypes:: Vector{Any} , @nospecialize (atype);
296
320
max_union_splitting:: Int = InferenceParams (interp). max_union_splitting,
@@ -308,43 +332,30 @@ is_union_split_eligible(𝕃::AbstractLattice, argtypes::Vector{Any}, max_union_
308
332
function find_union_split_method_matches (interp:: AbstractInterpreter , argtypes:: Vector{Any} ,
309
333
@nospecialize (atype), max_methods:: Int )
310
334
split_argtypes = switchtupleunion (typeinf_lattice (interp), argtypes)
311
- infos = MethodLookupResult []
335
+ infos = MethodMatchInfo []
312
336
applicable = Any[]
313
337
applicable_argtypes = Vector{Any}[] # arrays like `argtypes`, including constants, for each match
314
338
valid_worlds = WorldRange ()
315
- mts = MethodTable[]
316
- fullmatches = Bool[]
317
339
for i in 1 : length (split_argtypes)
318
340
arg_n = split_argtypes[i]:: Vector{Any}
319
341
sig_n = argtypes_to_type (arg_n)
320
342
mt = ccall (:jl_method_table_for , Any, (Any,), sig_n)
321
343
mt === nothing && return FailedMethodMatch (" Could not identify method table for call" )
322
344
mt = mt:: MethodTable
323
- matches = findall (sig_n, method_table (interp); limit = max_methods)
324
- if matches === nothing
345
+ thismatches = findall (sig_n, method_table (interp); limit = max_methods)
346
+ if thismatches === nothing
325
347
return FailedMethodMatch (" For one of the union split cases, too many methods matched" )
326
348
end
327
- push! (infos, matches)
328
- for m in matches
349
+ for m in thismatches
329
350
push! (applicable, m)
330
351
push! (applicable_argtypes, arg_n)
331
352
end
332
- valid_worlds = intersect (valid_worlds, matches. valid_worlds)
333
- thisfullmatch = any (match:: MethodMatch -> match. fully_covers, matches)
334
- mt_found = false
335
- for (i, mt′) in enumerate (mts)
336
- if mt′ === mt
337
- fullmatches[i] &= thisfullmatch
338
- mt_found = true
339
- break
340
- end
341
- end
342
- if ! mt_found
343
- push! (mts, mt)
344
- push! (fullmatches, thisfullmatch)
345
- end
353
+ valid_worlds = intersect (valid_worlds, thismatches. valid_worlds)
354
+ thisfullmatch = any (match:: MethodMatch -> match. fully_covers, thismatches)
355
+ thisinfo = MethodMatchInfo (thismatches, mt, thisfullmatch)
356
+ push! (infos, thisinfo)
346
357
end
347
- info = UnionSplitInfo (infos, mts, fullmatches )
358
+ info = UnionSplitInfo (infos)
348
359
return UnionSplitMethodMatches (
349
360
applicable, applicable_argtypes, info, valid_worlds)
350
361
end
@@ -583,14 +594,7 @@ function add_call_backedges!(interp::AbstractInterpreter, @nospecialize(rettype)
583
594
end
584
595
# also need an edge to the method table in case something gets
585
596
# added that did not intersect with any existing method
586
- if isa (matches, MethodMatches)
587
- fully_covering (matches) || add_mt_backedge! (sv, matches. info. mt, atype)
588
- else
589
- matches:: UnionSplitMethodMatches
590
- for (thisfullmatch, mt) in zip (matches. info. fullmatches, matches. info. mts)
591
- thisfullmatch || add_mt_backedge! (sv, mt, atype)
592
- end
593
- end
597
+ add_uncovered_edges! (sv, matches, atype)
594
598
return nothing
595
599
end
596
600
0 commit comments