Skip to content

Commit 3136189

Browse files
committed
inference: improve isa-constraint propagation for iskindtype objects
Currently our inference isn't able to propagate `isa`-based type constraint for cases like `isa(Type{<:...}, DataType)` since `typeintersect` may return `Type` object itself when taking `Type` object and `iskindtype`-object. This case happens in the following kind of situation (motivated by the discussion at <#46553 (comment)>): ```julia julia> function isa_kindtype(T::Type{<:AbstractVector}) if isa(T, DataType) # `T` here should be inferred as `DataType` rather than `Type{<:AbstractVector}` return T.name.name # should be inferred as ::Symbol end return nothing end isa_kindtype (generic function with 1 method) julia> only(code_typed(isa_kindtype; optimize=false)) CodeInfo( 1 ─ %1 = (T isa Main.DataType)::Bool └── goto #3 if not %1 2 ─ %3 = Base.getproperty(T, :name)::Any │ %4 = Base.getproperty(%3, :name)::Any └── return %4 3 ─ return Main.nothing ) => Any ``` This commit improves the situation by adding a special casing for abstract interpretation, rather than changing the behavior of `typeintersect`.
1 parent 9e8fb63 commit 3136189

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,10 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
15381538
tty_lb = tty_ub # TODO: this would be wrong if !isexact_tty, but instanceof_tfunc doesn't preserve this info
15391539
if !has_free_typevars(tty_lb) && !has_free_typevars(tty_ub)
15401540
ifty = typeintersect(aty, tty_ub)
1541+
if iskindtype(tty_ub) && ifty !== Bottom
1542+
# `typeintersect` may be unable narrow down `Type`-type
1543+
ifty = tty_ub
1544+
end
15411545
valid_as_lattice(ifty) || (ifty = Union{})
15421546
elty = typesubtract(aty, tty_lb, InferenceParams(interp).MAX_UNION_SPLITTING)
15431547
return Conditional(a, ifty, elty)
@@ -2678,14 +2682,22 @@ end
26782682
function conditional_change(state::VarTable, @nospecialize(typ), slot::Int)
26792683
vtype = state[slot]
26802684
oldtyp = vtype.typ
2681-
# approximate test for `typ ∩ oldtyp` being better than `oldtyp`
2682-
# since we probably formed these types with `typesubstract`, the comparison is likely simple
2683-
if ignorelimited(typ) ignorelimited(oldtyp)
2684-
# typ is better unlimited, but we may still need to compute the tmeet with the limit "causes" since we ignored those in the comparison
2685-
oldtyp isa LimitedAccuracy && (typ = tmerge(typ, LimitedAccuracy(Bottom, oldtyp.causes)))
2686-
return StateUpdate(SlotNumber(slot), VarState(typ, vtype.undef), state, true)
2685+
if iskindtype(typ)
2686+
# this code path corresponds to the special handling for `isa(x, iskindtype)` check
2687+
# implemented within `abstract_call_builtin`
2688+
elseif ignorelimited(typ) ignorelimited(oldtyp)
2689+
# approximate test for `typ ∩ oldtyp` being better than `oldtyp`
2690+
# since we probably formed these types with `typesubstract`,
2691+
# the comparison is likely simple
2692+
else
2693+
return nothing
26872694
end
2688-
return nothing
2695+
if oldtyp isa LimitedAccuracy
2696+
# typ is better unlimited, but we may still need to compute the tmeet with the limit
2697+
# "causes" since we ignored those in the comparison
2698+
typ = tmerge(typ, LimitedAccuracy(Bottom, oldtyp.causes))
2699+
end
2700+
return StateUpdate(SlotNumber(slot), VarState(typ, vtype.undef), state, true)
26892701
end
26902702

26912703
function bool_rt_to_conditional(@nospecialize(rt), slottypes::Vector{Any}, state::VarTable, slot_id::Int)

test/compiler/inference.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4202,3 +4202,12 @@ end
42024202
end
42034203
call_pure_annotated_loop(x) = Val{pure_annotated_loop(x, 1)}()
42044204
@test only(Base.return_types(call_pure_annotated_loop, Tuple{Int})) === Val{1}
4205+
4206+
function isa_kindtype(T::Type{<:AbstractVector})
4207+
if isa(T, DataType)
4208+
# `T` here should be inferred as `DataType` rather than `Type{<:AbstractVector}`
4209+
return T.name.name # should be inferred as ::Symbol
4210+
end
4211+
return nothing
4212+
end
4213+
@test only(Base.return_types(isa_kindtype)) === Union{Nothing,Symbol}

0 commit comments

Comments
 (0)