Skip to content

Commit 3de6f70

Browse files
committed
inference: eliminate more potential widenconst(::TypeofVararg) cases
Follows #42583. The missing case within `const_prop_function_heuristic` was originally reported from RationalAI's test suite. I added the other two cases by some code review.
1 parent f3d505d commit 3de6f70

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -766,14 +766,14 @@ function const_prop_function_heuristic(
766766
# but highly worthwhile to inline promote of a constant
767767
length(argtypes) > 2 || return false
768768
t1 = widenconst(argtypes[2])
769-
all_same = true
770769
for i in 3:length(argtypes)
771-
if widenconst(argtypes[i]) !== t1
772-
all_same = false
773-
break
770+
at = argtypes[i]
771+
ty = isvarargtype(at) ? unwraptv(at) : widenconst(at)
772+
if ty !== t1
773+
return true
774774
end
775775
end
776-
return !all_same
776+
return false
777777
end
778778
return true
779779
end
@@ -1344,9 +1344,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
13441344
return CallMeta(Any, false)
13451345
elseif f === Core.kwfunc
13461346
if la == 2
1347-
ft = widenconst(argtypes[2])
1348-
if isa(ft, DataType) && isdefined(ft.name, :mt) && isdefined(ft.name.mt, :kwsorter)
1349-
return CallMeta(Const(ft.name.mt.kwsorter), MethodResultPure())
1347+
aty = argtypes[2]
1348+
if !isvarargtype(aty)
1349+
ft = widenconst(aty)
1350+
if isa(ft, DataType) && isdefined(ft.name, :mt) && isdefined(ft.name.mt, :kwsorter)
1351+
return CallMeta(Const(ft.name.mt.kwsorter), MethodResultPure())
1352+
end
13501353
end
13511354
end
13521355
return CallMeta(Any, false)
@@ -1366,8 +1369,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
13661369
return CallMeta(typevar_tfunc(n, lb_var, ub_var), false)
13671370
elseif f === UnionAll
13681371
return CallMeta(abstract_call_unionall(argtypes), false)
1369-
elseif f === Tuple && la == 2 && !isconcretetype(widenconst(argtypes[2]))
1370-
return CallMeta(Tuple, false)
1372+
elseif f === Tuple && la == 2
1373+
aty = argtypes[2]
1374+
ty = isvarargtype(aty) ? unwrapva(aty) : widenconst(aty)
1375+
if !isconcretetype(ty)
1376+
return CallMeta(Tuple, false)
1377+
end
13711378
elseif is_return_type(f)
13721379
return return_type_tfunc(interp, argtypes, sv)
13731380
elseif la == 2 && istopfunction(f, :!)

test/compiler/inference.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3667,6 +3667,35 @@ let
36673667
@test argtypes[11] == Tuple{Integer,Integer}
36683668
end
36693669

3670+
# make sure not to call `widenconst` on `TypeofVararg` objects
3671+
@testset "unhandled Vararg" begin
3672+
struct UnhandledVarargCond
3673+
val::Bool
3674+
end
3675+
function Base.:+(a::UnhandledVarargCond, xs...)
3676+
if a.val
3677+
return nothing
3678+
else
3679+
s = 0
3680+
for x in xs
3681+
s += x
3682+
end
3683+
return s
3684+
end
3685+
end
3686+
@test Base.return_types((Vector{Int},)) do xs
3687+
+(UnhandledVarargCond(false), xs...)
3688+
end |> only === Int
3689+
3690+
@test (Base.return_types((Vector{Any},)) do xs
3691+
Core.kwfunc(xs...)
3692+
end; true)
3693+
3694+
@test Base.return_types((Vector{Vector{Int}},)) do xs
3695+
Tuple(xs...)
3696+
end |> only === Tuple{Vararg{Int}}
3697+
end
3698+
36703699
# issue #42646
36713700
@test only(Base.return_types(getindex, (Array{undef}, Int))) >: Union{} # check that it does not throw
36723701

0 commit comments

Comments
 (0)