Skip to content

Commit c2657da

Browse files
vtjnashkpamnany
authored andcommitted
inference: ensure inferring reachable code methods (JuliaLang#57088)
PR JuliaLang#51317 was a bit over-eager about inferring inferring unreachable code methods. Filter out the Vararg case, since that can be handled by simply removing it instead of discarding the whole call. Fixes JuliaLang#56628 (cherry picked from commit eb9f24c)
1 parent 94b692f commit c2657da

File tree

5 files changed

+22
-4
lines changed

5 files changed

+22
-4
lines changed

base/compiler/abstractinterpretation.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ function find_matching_methods(𝕃::AbstractLattice,
243243
for i in 1:length(split_argtypes)
244244
arg_n = split_argtypes[i]::Vector{Any}
245245
sig_n = argtypes_to_type(arg_n)
246+
sig_n === Bottom && continue
246247
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
247248
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
248249
mt = mt::MethodTable
@@ -508,7 +509,7 @@ function abstract_call_method(interp::AbstractInterpreter,
508509
sigtuple = unwrap_unionall(sig)
509510
sigtuple isa DataType ||
510511
return MethodCallResult(Any, false, false, nothing, Effects())
511-
all(@nospecialize(x) -> valid_as_lattice(unwrapva(x), true), sigtuple.parameters) ||
512+
all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), sigtuple.parameters) ||
512513
return MethodCallResult(Union{}, false, false, nothing, EFFECTS_THROWS) # catch bad type intersections early
513514

514515
if is_nospecializeinfer(method)
@@ -2166,6 +2167,7 @@ function abstract_call_unknown(interp::AbstractInterpreter, @nospecialize(ft),
21662167
end
21672168
# non-constant function, but the number of arguments is known and the `f` is not a builtin or intrinsic
21682169
atype = argtypes_to_type(arginfo.argtypes)
2170+
atype === Bottom && return CallMeta(Union{}, Union{}, EFFECTS_THROWS, NoCallInfo()) # accidentally unreachable
21692171
return abstract_call_gf_by_type(interp, nothing, arginfo, si, atype, sv, max_methods)
21702172
end
21712173

base/compiler/ssair/inlining.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -1450,8 +1450,9 @@ function handle_call!(todo::Vector{Pair{Int,Any}},
14501450
cases = compute_inlining_cases(info, flag, sig, state)
14511451
cases === nothing && return nothing
14521452
cases, all_covered, joint_effects = cases
1453-
handle_cases!(todo, ir, idx, stmt, argtypes_to_type(sig.argtypes), cases,
1454-
all_covered, joint_effects)
1453+
atype = argtypes_to_type(sig.argtypes)
1454+
atype === Union{} && return nothing # accidentally actually unreachable
1455+
handle_cases!(todo, ir, idx, stmt, atype, cases, all_covered, joint_effects)
14551456
end
14561457

14571458
function handle_match!(cases::Vector{InliningCase},

base/compiler/tfuncs.jl

+4
Original file line numberDiff line numberDiff line change
@@ -2689,6 +2689,10 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any},
26892689
isvarargtype(argtypes[2]) && return CallMeta(Bool, EFFECTS_UNKNOWN, NoCallInfo())
26902690
argtypes = argtypes[2:end]
26912691
atype = argtypes_to_type(argtypes)
2692+
if atype === Union{}
2693+
rt = Union{} # accidentally unreachable code
2694+
return CallMeta(rt, EFFECTS_TOTAL, NoCallInfo())
2695+
end
26922696
matches = find_matching_methods(typeinf_lattice(interp), argtypes, atype, method_table(interp),
26932697
InferenceParams(interp).max_union_splitting, max_methods)
26942698
if isa(matches, FailedMethodMatch)

base/compiler/typeutils.jl

+6-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ has_extended_info(@nospecialize x) = (!isa(x, Type) && !isvarargtype(x)) || isTy
5454
# certain combinations of `a` and `b` where one/both isa/are `Union`/`UnionAll` type(s)s.
5555
isnotbrokensubtype(@nospecialize(a), @nospecialize(b)) = (!iskindtype(b) || !isType(a) || hasuniquerep(a.parameters[1]) || b <: a)
5656

57-
argtypes_to_type(argtypes::Array{Any,1}) = Tuple{anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes)...}
57+
function argtypes_to_type(argtypes::Array{Any,1})
58+
argtypes = anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes)
59+
filter!(@nospecialize(x) -> !isvarargtype(x) || valid_as_lattice(unwrapva(x), true), argtypes)
60+
all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), argtypes) || return Bottom
61+
return Tuple{argtypes...}
62+
end
5863

5964
function isknownlength(t::DataType)
6065
isvatuple(t) || return true

test/compiler/inference.jl

+6
Original file line numberDiff line numberDiff line change
@@ -5206,3 +5206,9 @@ end
52065206
@test only(Base.return_types((x,f) -> getfield(x, f), (An51317, Symbol))) === Int
52075207
@test only(Base.return_types(x -> getfield(x, :b), (A51317,))) === Union{}
52085208
@test only(Base.return_types(x -> getfield(x, :b), (An51317,))) === Union{}
5209+
5210+
# issue #56628
5211+
@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}} ]) === Tuple{Int, UnitRange{Int}}
5212+
@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64 ]) === Tuple{Int, UnitRange{Int}, Float64}
5213+
@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64, Tuple{2} ]) === Union{}
5214+
@test Base.return_types(Tuple{Tuple{Int, Vararg{Pair{Any, Union{}}}}},) do x; Returns(true)(x...); end |> only === Bool

0 commit comments

Comments
 (0)