Skip to content

Commit 643fef7

Browse files
aviateskKristofferC
authored andcommitted
inference: eliminate more potential widenconst(::TypeofVararg) cases (#42971)
Follows #42583. The missing case within `const_prop_function_heuristic` was originally reported from RerationalAI's test suite. I added the other two cases by some code review. (cherry picked from commit 71d57d9)
1 parent 2a4d14f commit 643fef7

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
@@ -685,14 +685,14 @@ function const_prop_function_heuristic(interp::AbstractInterpreter, @nospecializ
685685
# but highly worthwhile to inline promote of a constant
686686
length(argtypes) > 2 || return false
687687
t1 = widenconst(argtypes[2])
688-
all_same = true
689688
for i in 3:length(argtypes)
690-
if widenconst(argtypes[i]) !== t1
691-
all_same = false
692-
break
689+
at = argtypes[i]
690+
ty = isvarargtype(at) ? unwraptv(at) : widenconst(at)
691+
if ty !== t1
692+
return true
693693
end
694694
end
695-
return !all_same
695+
return false
696696
end
697697
return true
698698
end
@@ -1255,9 +1255,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
12551255
return CallMeta(abstract_call_builtin(interp, f, fargs, argtypes, sv, max_methods), false)
12561256
elseif f === Core.kwfunc
12571257
if la == 2
1258-
ft = widenconst(argtypes[2])
1259-
if isa(ft, DataType) && isdefined(ft.name, :mt) && isdefined(ft.name.mt, :kwsorter)
1260-
return CallMeta(Const(ft.name.mt.kwsorter), MethodResultPure())
1258+
aty = argtypes[2]
1259+
if !isvarargtype(aty)
1260+
ft = widenconst(aty)
1261+
if isa(ft, DataType) && isdefined(ft.name, :mt) && isdefined(ft.name.mt, :kwsorter)
1262+
return CallMeta(Const(ft.name.mt.kwsorter), MethodResultPure())
1263+
end
12611264
end
12621265
end
12631266
return CallMeta(Any, false)
@@ -1277,8 +1280,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
12771280
return CallMeta(typevar_tfunc(n, lb_var, ub_var), false)
12781281
elseif f === UnionAll
12791282
return CallMeta(abstract_call_unionall(argtypes), false)
1280-
elseif f === Tuple && la == 2 && !isconcretetype(widenconst(argtypes[2]))
1281-
return CallMeta(Tuple, false)
1283+
elseif f === Tuple && la == 2
1284+
aty = argtypes[2]
1285+
ty = isvarargtype(aty) ? unwrapva(aty) : widenconst(aty)
1286+
if !isconcretetype(ty)
1287+
return CallMeta(Tuple, false)
1288+
end
12821289
elseif is_return_type(f)
12831290
return return_type_tfunc(interp, argtypes, sv)
12841291
elseif la == 2 && istopfunction(f, :!)

test/compiler/inference.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3545,3 +3545,32 @@ let
35453545
@test argtypes[10] == Any
35463546
@test argtypes[11] == Tuple{Integer,Integer}
35473547
end
3548+
3549+
# make sure not to call `widenconst` on `TypeofVararg` objects
3550+
@testset "unhandled Vararg" begin
3551+
struct UnhandledVarargCond
3552+
val::Bool
3553+
end
3554+
function Base.:+(a::UnhandledVarargCond, xs...)
3555+
if a.val
3556+
return nothing
3557+
else
3558+
s = 0
3559+
for x in xs
3560+
s += x
3561+
end
3562+
return s
3563+
end
3564+
end
3565+
@test Base.return_types((Vector{Int},)) do xs
3566+
+(UnhandledVarargCond(false), xs...)
3567+
end |> only === Int
3568+
3569+
@test (Base.return_types((Vector{Any},)) do xs
3570+
Core.kwfunc(xs...)
3571+
end; true)
3572+
3573+
@test Base.return_types((Vector{Vector{Int}},)) do xs
3574+
Tuple(xs...)
3575+
end |> only === Tuple{Vararg{Int}}
3576+
end

0 commit comments

Comments
 (0)