@@ -29,9 +29,13 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
2929 fullmatch = Bool[]
3030 if splitunions
3131 splitsigs = switchtupleunion (atype)
32+ split_argtypes = switchtupleunion (argtypes)
3233 applicable = Any[]
34+ # arrays like `argtypes`, including constants, for each match
35+ applicable_argtypes = Vector{Any}[]
3336 infos = MethodMatchInfo[]
34- for sig_n in splitsigs
37+ for j in 1 : length (splitsigs)
38+ sig_n = splitsigs[j]
3539 mt = ccall (:jl_method_table_for , Any, (Any,), sig_n)
3640 if mt === nothing
3741 add_remark! (interp, sv, " Could not identify method table for call" )
@@ -45,6 +49,9 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
4549 end
4650 push! (infos, MethodMatchInfo (matches))
4751 append! (applicable, matches)
52+ for _ in 1 : length (matches)
53+ push! (applicable_argtypes, split_argtypes[j])
54+ end
4855 valid_worlds = intersect (valid_worlds, matches. valid_worlds)
4956 thisfullmatch = _any (match-> (match:: MethodMatch ). fully_covers, matches)
5057 found = false
@@ -80,6 +87,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
8087 info = MethodMatchInfo (matches)
8188 applicable = matches. matches
8289 valid_worlds = matches. valid_worlds
90+ applicable_argtypes = nothing
8391 end
8492 update_valid_age! (sv, valid_worlds)
8593 applicable = applicable:: Array{Any,1}
@@ -136,6 +144,9 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
136144 if this_rt != = Bottom
137145 if nonbot === 0
138146 nonbot = i
147+ elseif nonbot === - 1
148+ elseif method === (applicable[nonbot]:: MethodMatch ). method
149+ # another entry from the same method, due to union splitting
139150 else
140151 nonbot = - 1
141152 end
@@ -147,12 +158,23 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
147158 # try constant propagation if only 1 method is inferred to non-Bottom
148159 # this is in preparation for inlining, or improving the return result
149160 is_unused = call_result_unused (sv)
150- if nonbot > 0 && seen == napplicable && (! edgecycle || ! is_unused) && isa (rettype, Type) && InferenceParams (interp). ipo_constant_propagation
161+ if nonbot > 0 && seen == napplicable && (! edgecycle || ! is_unused) &&
162+ (isa (rettype, Type) || isa (rettype, PartialStruct)) && InferenceParams (interp). ipo_constant_propagation
151163 # if there's a possibility we could constant-propagate a better result
152164 # (hopefully without doing too much work), try to do that now
153165 # TODO : it feels like this could be better integrated into abstract_call_method / typeinf_edge
154- const_rettype = abstract_call_method_with_const_args (interp, rettype, f, argtypes, applicable[nonbot]:: MethodMatch , sv, edgecycle)
155- if const_rettype ⊑ rettype
166+ const_rettype = Bottom
167+ for i in 1 : napplicable
168+ mm = applicable[i]:: MethodMatch
169+ if i === nonbot || mm. method === (applicable[nonbot]:: MethodMatch ). method
170+ this_argtypes = applicable_argtypes === nothing ? argtypes : applicable_argtypes[i]
171+ one_rettype = abstract_call_method_with_const_args (interp, rettype, f, this_argtypes, mm, sv, edgecycle)
172+ const_rettype = tmerge (const_rettype, one_rettype)
173+ const_rettype ⊑ rettype || (const_rettype = Any)
174+ const_rettype === Any && break
175+ end
176+ end
177+ if const_rettype != = Any
156178 # use the better result, if it's a refinement of rettype
157179 rettype = const_rettype
158180 end
0 commit comments