Skip to content

Commit d51b1d1

Browse files
vtjnashaviatesk
authored andcommitted
inference: bail from const-prop if const-prop fails
Otherwise we can can end up in an infinite cycle of attempting const-prop, and that failing. Also handle Varargs in method-lookup matching, which was the cause for which we could not compute the const-prop signature. Fixes #42097
1 parent 3aea11e commit d51b1d1

File tree

3 files changed

+29
-16
lines changed

3 files changed

+29
-16
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,10 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul
546546
end
547547
end
548548
inf_result = InferenceResult(mi, argtypes, va_override)
549+
if !any(inf_result.overridden_by_const)
550+
add_remark!(interp, sv, "[constprop] Could not handle constant info in matching_cache_argtypes")
551+
return nothing
552+
end
549553
frame = InferenceState(inf_result, #=cache=#:local, interp)
550554
frame === nothing && return nothing # this is probably a bad generated function (unsound), but just ignore it
551555
frame.parent = sv

base/compiler/inferenceresult.jl

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,32 @@ end
1616
function matching_cache_argtypes(linfo::MethodInstance, given_argtypes::Vector, va_override::Bool)
1717
@assert isa(linfo.def, Method) # ensure the next line works
1818
nargs::Int = linfo.def.nargs
19-
@assert length(given_argtypes) >= (nargs - 1)
2019
given_argtypes = anymap(widenconditional, given_argtypes)
21-
if va_override || linfo.def.isva
20+
isva = va_override || linfo.def.isva
21+
if isva || isvarargtype(given_argtypes[end])
2222
isva_given_argtypes = Vector{Any}(undef, nargs)
23-
for i = 1:(nargs - 1)
23+
for i = 1:(nargs - isva)
2424
isva_given_argtypes[i] = argtype_by_index(given_argtypes, i)
2525
end
26-
if length(given_argtypes) >= nargs || !isvarargtype(given_argtypes[end])
27-
isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[nargs:end])
28-
else
29-
isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[end:end])
26+
if isva
27+
if length(given_argtypes) < nargs && isvarargtype(given_argtypes[end])
28+
last = length(given_argtypes)
29+
else
30+
last = nargs
31+
end
32+
isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[last:end])
3033
end
3134
given_argtypes = isva_given_argtypes
3235
end
36+
@assert length(given_argtypes) == nargs
3337
cache_argtypes, overridden_by_const = matching_cache_argtypes(linfo, nothing, va_override)
34-
if nargs === length(given_argtypes)
35-
for i in 1:nargs
36-
given_argtype = given_argtypes[i]
37-
cache_argtype = cache_argtypes[i]
38-
if !is_argtype_match(given_argtype, cache_argtype, overridden_by_const[i])
39-
# prefer the argtype we were given over the one computed from `linfo`
40-
cache_argtypes[i] = given_argtype
41-
overridden_by_const[i] = true
42-
end
38+
for i in 1:nargs
39+
given_argtype = given_argtypes[i]
40+
cache_argtype = cache_argtypes[i]
41+
if !is_argtype_match(given_argtype, cache_argtype, overridden_by_const[i])
42+
# prefer the argtype we were given over the one computed from `linfo`
43+
cache_argtypes[i] = given_argtype
44+
overridden_by_const[i] = true
4345
end
4446
end
4547
return cache_argtypes, overridden_by_const

test/compiler/inference.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,3 +3496,10 @@ end
34963496
end
34973497
return x
34983498
end) === Union{Int, Float64, Char}
3499+
3500+
# issue #42097
3501+
struct Foo42097{F} end
3502+
Foo42097(f::F, args) where {F} = Foo42097{F}()
3503+
Foo42097(A) = Foo42097(Base.inferencebarrier(+), Base.inferencebarrier(1)...)
3504+
foo42097() = Foo42097([1]...)
3505+
@test foo42097() isa Foo42097{typeof(+)}

0 commit comments

Comments
 (0)