diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index ff6ac7c99bfa5..8630092353df3 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -180,14 +180,21 @@ function abstract_call_method_with_const_args(@nospecialize(f), argtypes::Vector atypes = get_argtypes(inf_result) if method.isva vargs = argtypes[(nargs + 1):end] + all_vargs_const = true for i in 1:length(vargs) a = maybe_widen_conditional(vargs[i]) + all_vargs_const &= a isa Const if i > length(inf_result.vargs) push!(inf_result.vargs, a) elseif a isa Const inf_result.vargs[i] = a end end + # If all vargs are const, the result may be a constant + # tuple. If so, we should make sure to treat it as such + if all_vargs_const + atypes[nargs + 1] = builtin_tfunction(tuple, inf_result.vargs, sv) + end end for i in 1:nargs a = maybe_widen_conditional(argtypes[i]) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 35bf123e1597b..0cb113014e9ed 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -2030,3 +2030,10 @@ get_order_kwargs(; by = identity, func = isless, rev = false) = get_order(by, fu # test that this doesn't cause an internal error get_order_kwargs() end + +# Test that tail-like functions don't block constant propagation +my_tail_const_prop(i, tail...) = tail +function foo_tail_const_prop() + Val{my_tail_const_prop(1,2,3,4)}() +end +@test (@inferred foo_tail_const_prop()) == Val{(2,3,4)}()