From d51b1d1afbd0232f6590d28adf2fd8aae2ca7a9d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 3 Sep 2021 14:16:03 -0400 Subject: [PATCH] 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 --- base/compiler/abstractinterpretation.jl | 4 +++ base/compiler/inferenceresult.jl | 34 +++++++++++++------------ test/compiler/inference.jl | 7 +++++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 2bb3943a3f83f..492afa9b8ec1c 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -546,6 +546,10 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul end end inf_result = InferenceResult(mi, argtypes, va_override) + if !any(inf_result.overridden_by_const) + add_remark!(interp, sv, "[constprop] Could not handle constant info in matching_cache_argtypes") + return nothing + end frame = InferenceState(inf_result, #=cache=#:local, interp) frame === nothing && return nothing # this is probably a bad generated function (unsound), but just ignore it frame.parent = sv diff --git a/base/compiler/inferenceresult.jl b/base/compiler/inferenceresult.jl index 026b5286979cb..483e2f38d9ee8 100644 --- a/base/compiler/inferenceresult.jl +++ b/base/compiler/inferenceresult.jl @@ -16,30 +16,32 @@ end function matching_cache_argtypes(linfo::MethodInstance, given_argtypes::Vector, va_override::Bool) @assert isa(linfo.def, Method) # ensure the next line works nargs::Int = linfo.def.nargs - @assert length(given_argtypes) >= (nargs - 1) given_argtypes = anymap(widenconditional, given_argtypes) - if va_override || linfo.def.isva + isva = va_override || linfo.def.isva + if isva || isvarargtype(given_argtypes[end]) isva_given_argtypes = Vector{Any}(undef, nargs) - for i = 1:(nargs - 1) + for i = 1:(nargs - isva) isva_given_argtypes[i] = argtype_by_index(given_argtypes, i) end - if length(given_argtypes) >= nargs || !isvarargtype(given_argtypes[end]) - isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[nargs:end]) - else - isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[end:end]) + if isva + if length(given_argtypes) < nargs && isvarargtype(given_argtypes[end]) + last = length(given_argtypes) + else + last = nargs + end + isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[last:end]) end given_argtypes = isva_given_argtypes end + @assert length(given_argtypes) == nargs cache_argtypes, overridden_by_const = matching_cache_argtypes(linfo, nothing, va_override) - if nargs === length(given_argtypes) - for i in 1:nargs - given_argtype = given_argtypes[i] - cache_argtype = cache_argtypes[i] - if !is_argtype_match(given_argtype, cache_argtype, overridden_by_const[i]) - # prefer the argtype we were given over the one computed from `linfo` - cache_argtypes[i] = given_argtype - overridden_by_const[i] = true - end + for i in 1:nargs + given_argtype = given_argtypes[i] + cache_argtype = cache_argtypes[i] + if !is_argtype_match(given_argtype, cache_argtype, overridden_by_const[i]) + # prefer the argtype we were given over the one computed from `linfo` + cache_argtypes[i] = given_argtype + overridden_by_const[i] = true end end return cache_argtypes, overridden_by_const diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 2b85fcbfc943e..9ad091f08e582 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -3496,3 +3496,10 @@ end end return x end) === Union{Int, Float64, Char} + +# issue #42097 +struct Foo42097{F} end +Foo42097(f::F, args) where {F} = Foo42097{F}() +Foo42097(A) = Foo42097(Base.inferencebarrier(+), Base.inferencebarrier(1)...) +foo42097() = Foo42097([1]...) +@test foo42097() isa Foo42097{typeof(+)}