Skip to content

Commit bbf10e0

Browse files
aviateskserenity4
andauthored
inference: avoid creating PartialStruct that never exists at runtime (JuliaLang#57720)
Specifically, when `form_partially_defined_struct` tries to create a `PartialStruct`, this commit adds extra checks to prevent creating it if it doesn't exist at runtime. While it would be better to avoid propagating these runtime-invalid object types altogether, that would require a major overhaul of the dispatch system. As a fix within the current dispatch system, this commit is proposed. - closes JuliaLang#57673 Co-authored-by: Cédric Belmant <[email protected]>
1 parent b076af4 commit bbf10e0

File tree

4 files changed

+20
-3
lines changed

4 files changed

+20
-3
lines changed

src/abstractinterpretation.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2156,7 +2156,11 @@ function form_partially_defined_struct(𝕃ᵢ::AbstractLattice, @nospecialize(o
21562156
if fields[fldidx] === Union{}
21572157
return nothing # `Union{}` field never transitions to be defined
21582158
end
2159-
undefs = partialstruct_init_undefs(objt, fldcnt)
2159+
undefs = partialstruct_init_undefs(objt, fields)
2160+
if undefs === nothing
2161+
# this object never exists at runtime, avoid creating unprofitable `PartialStruct`
2162+
return nothing
2163+
end
21602164
undefs[fldidx] = false
21612165
return PartialStruct(𝕃ᵢ, objt0, undefs, fields)
21622166
end

src/tfuncs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1995,7 +1995,7 @@ function tuple_tfunc(𝕃::AbstractLattice, argtypes::Vector{Any})
19951995
typ = Tuple{params...}
19961996
# replace a singleton type with its equivalent Const object
19971997
issingletontype(typ) && return Const(typ.instance)
1998-
return anyinfo ? PartialStruct(𝕃, typ, partialstruct_init_undefs(typ, argtypes), argtypes) : typ
1998+
return anyinfo ? PartialStruct(𝕃, typ, partialstruct_init_undefs(typ, argtypes)::Vector, argtypes) : typ
19991999
end
20002000

20012001
@nospecs function memorynew_tfunc(𝕃::AbstractLattice, memtype, memlen)

src/typelattice.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,9 @@ end
755755

756756
# Legacy constructor
757757
function Core.PartialStruct(𝕃::AbstractLattice, @nospecialize(typ), fields::Vector{Any})
758-
return PartialStruct(𝕃, typ, partialstruct_init_undefs(typ, fields), fields)
758+
undefs = partialstruct_init_undefs(typ, fields)
759+
undefs === nothing && error("This object never exists at runtime")
760+
return PartialStruct(𝕃, typ, undefs, fields)
759761
end
760762

761763
function Core.PartialStruct(::AbstractLattice, @nospecialize(typ), undefs::Vector{Union{Nothing,Bool}}, fields::Vector{Any})

test/inference.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6382,4 +6382,15 @@ g57292(xs::String...) = getfield(("abc",), 1, :not_atomic, xs...)
63826382
@test Base.infer_return_type(f57292) == String
63836383
@test Base.infer_return_type(g57292) == String
63846384

6385+
mutable struct Issue57673{C<:Union{Int,Float64}}
6386+
c::C
6387+
d
6388+
Issue57673(c::C, d) where C = new{C}(c, d)
6389+
Issue57673(c::C) where C = new{C}(c)
6390+
end
6391+
@test Base.infer_return_type((Issue57673,)) do a::Issue57673{<:String}
6392+
setfield!(a, :d, nothing)
6393+
a
6394+
end === Union{} # `setfield!` tfunc should be able to figure out this object is runtime invalid
6395+
63856396
end # module inference

0 commit comments

Comments
 (0)