Skip to content

Commit 7e515b1

Browse files
authored
inference: prevent nested slot wrappers in abstract_call_builtin (#58249)
1 parent 75ba594 commit 7e515b1

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

Compiler/src/abstractinterpretation.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,8 +1402,9 @@ function matching_cache_argtypes(𝕃::AbstractLattice, mi::MethodInstance,
14021402
if slotid !== nothing
14031403
# using union-split signature, we may be able to narrow down `Conditional`
14041404
sigt = widenconst(slotid > nargs ? argtypes[slotid] : cache_argtypes[slotid])
1405-
thentype = tmeet(cnd.thentype, sigt)
1406-
elsetype = tmeet(cnd.elsetype, sigt)
1405+
= meet(𝕃)
1406+
thentype = cnd.thentype sigt
1407+
elsetype = cnd.elsetype sigt
14071408
if thentype === Bottom && elsetype === Bottom
14081409
# we accidentally proved this method match is impossible
14091410
# TODO bail out here immediately rather than just propagating Bottom ?
@@ -2119,7 +2120,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
21192120
else
21202121
thentype = form_partially_defined_struct(𝕃ᵢ, argtype2, argtypes[3])
21212122
if thentype !== nothing
2122-
elsetype = argtype2
2123+
elsetype = widenslotwrapper(argtype2)
21232124
if rt === Const(false)
21242125
thentype = Bottom
21252126
elseif rt === Const(true)
@@ -3254,7 +3255,7 @@ function abstract_eval_isdefined_expr(interp::AbstractInterpreter, e::Expr, ssta
32543255
elseif !vtyp.undef
32553256
rt = Const(true) # definitely assigned previously
32563257
else # form `Conditional` to refine `vtyp.undef` in the then branch
3257-
rt = Conditional(sym, vtyp.typ, vtyp.typ; isdefined=true)
3258+
rt = Conditional(sym, widenslotwrapper(vtyp.typ), widenslotwrapper(vtyp.typ); isdefined=true)
32583259
end
32593260
return RTEffects(rt, Union{}, EFFECTS_TOTAL)
32603261
end

Compiler/test/inference.jl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,12 +2264,18 @@ struct AliasableFields{S,T}
22642264
f1::S
22652265
f2::T
22662266
end
2267+
struct NullableAliasableFields{S,T}
2268+
f1::S
2269+
f2::T
2270+
NullableAliasableFields(f1::S, f2::T) where {S,T} = new{S,T}(f1, f2)
2271+
NullableAliasableFields(f1::S) where {S} = new{S,Union{}}(f1)
2272+
end
22672273
mutable struct AliasableConstField{S,T}
22682274
const f1::S
22692275
f2::T
22702276
end
22712277

2272-
import .Compiler:
2278+
using .Compiler:
22732279
InferenceLattice, MustAliasesLattice, InterMustAliasesLattice,
22742280
BaseInferenceLattice, SimpleInferenceLattice, IPOResultLattice, typeinf_lattice, ipo_lattice, optimizer_lattice
22752281

@@ -2282,7 +2288,7 @@ Compiler.optimizer_lattice(::MustAliasInterpreter) = SimpleInferenceLattice.inst
22822288
# lattice
22832289
# -------
22842290

2285-
import .Compiler: MustAlias, Const, PartialStruct, , tmerge
2291+
using .Compiler: MustAlias, Const, PartialStruct, , tmerge
22862292
let 𝕃ᵢ = InferenceLattice(MustAliasesLattice(BaseInferenceLattice.instance))
22872293
(@nospecialize(a), @nospecialize(b)) = Compiler.:(𝕃ᵢ, a, b)
22882294
tmerge(@nospecialize(a), @nospecialize(b)) = Compiler.tmerge(𝕃ᵢ, a, b)
@@ -2520,6 +2526,15 @@ jet509_hasitems(list) = length(list) >= 1
25202526
error("list is empty")
25212527
end |> only == Vector{Int}
25222528

2529+
# don't form nested slot wrappers
2530+
@test Base.infer_return_type((NullableAliasableFields{NullableAliasableFields},); interp=MustAliasInterpreter()) do x
2531+
y = getfield(x, :f1)
2532+
if isdefined(y, :f2) && isa(getfield(y, :f2), Int)
2533+
return getfield(y, :f2)
2534+
end
2535+
return 0
2536+
end == Int
2537+
25232538
# === constraint
25242539
# --------------
25252540

0 commit comments

Comments
 (0)