Skip to content

Commit

Permalink
inference: eliminate more potential widenconst(::TypeofVararg) cases (
Browse files Browse the repository at this point in the history
#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.
  • Loading branch information
aviatesk authored Nov 7, 2021
1 parent 36304ba commit 71d57d9
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 10 deletions.
27 changes: 17 additions & 10 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -766,14 +766,14 @@ function const_prop_function_heuristic(
# but highly worthwhile to inline promote of a constant
length(argtypes) > 2 || return false
t1 = widenconst(argtypes[2])
all_same = true
for i in 3:length(argtypes)
if widenconst(argtypes[i]) !== t1
all_same = false
break
at = argtypes[i]
ty = isvarargtype(at) ? unwraptv(at) : widenconst(at)
if ty !== t1
return true
end
end
return !all_same
return false
end
return true
end
Expand Down Expand Up @@ -1344,9 +1344,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
return CallMeta(Any, false)
elseif f === Core.kwfunc
if la == 2
ft = widenconst(argtypes[2])
if isa(ft, DataType) && isdefined(ft.name, :mt) && isdefined(ft.name.mt, :kwsorter)
return CallMeta(Const(ft.name.mt.kwsorter), MethodResultPure())
aty = argtypes[2]
if !isvarargtype(aty)
ft = widenconst(aty)
if isa(ft, DataType) && isdefined(ft.name, :mt) && isdefined(ft.name.mt, :kwsorter)
return CallMeta(Const(ft.name.mt.kwsorter), MethodResultPure())
end
end
end
return CallMeta(Any, false)
Expand All @@ -1366,8 +1369,12 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
return CallMeta(typevar_tfunc(n, lb_var, ub_var), false)
elseif f === UnionAll
return CallMeta(abstract_call_unionall(argtypes), false)
elseif f === Tuple && la == 2 && !isconcretetype(widenconst(argtypes[2]))
return CallMeta(Tuple, false)
elseif f === Tuple && la == 2
aty = argtypes[2]
ty = isvarargtype(aty) ? unwrapva(aty) : widenconst(aty)
if !isconcretetype(ty)
return CallMeta(Tuple, false)
end
elseif is_return_type(f)
return return_type_tfunc(interp, argtypes, sv)
elseif la == 2 && istopfunction(f, :!)
Expand Down
29 changes: 29 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3667,6 +3667,35 @@ let
@test argtypes[11] == Tuple{Integer,Integer}
end

# make sure not to call `widenconst` on `TypeofVararg` objects
@testset "unhandled Vararg" begin
struct UnhandledVarargCond
val::Bool
end
function Base.:+(a::UnhandledVarargCond, xs...)
if a.val
return nothing
else
s = 0
for x in xs
s += x
end
return s
end
end
@test Base.return_types((Vector{Int},)) do xs
+(UnhandledVarargCond(false), xs...)
end |> only === Int

@test (Base.return_types((Vector{Any},)) do xs
Core.kwfunc(xs...)
end; true)

@test Base.return_types((Vector{Vector{Int}},)) do xs
Tuple(xs...)
end |> only === Tuple{Vararg{Int}}
end

# issue #42646
@test only(Base.return_types(getindex, (Array{undef}, Int))) >: Union{} # check that it does not throw

Expand Down

0 comments on commit 71d57d9

Please sign in to comment.