Skip to content

Commit

Permalink
defined -> undef
Browse files Browse the repository at this point in the history
  • Loading branch information
Cédric Belmant committed Feb 11, 2025
1 parent 201c956 commit 8a9f31d
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 47 deletions.
8 changes: 4 additions & 4 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2153,11 +2153,11 @@ function form_partially_defined_struct(@nospecialize(obj), @nospecialize(name))
fldidx > nminfld || return nothing
fields = Any[fieldtype(objt0, i) for i in 1:nminfld]
nmaxfld = something(datatype_fieldcount(objt), fldidx)
defined = falses(nmaxfld)
for i in 1:nminfld defined[i] = true end
defined[fldidx] = true
undef = trues(nmaxfld)
for i in 1:nminfld undef[i] = false end
undef[fldidx] = false
push!(fields, fieldtype(objt0, fldidx))
return PartialStruct(fallback_lattice, objt0, defined, fields)
return PartialStruct(fallback_lattice, objt0, undef, fields)
end

function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{Any}, call::CallMeta)
Expand Down
22 changes: 11 additions & 11 deletions Compiler/src/typelattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -431,14 +431,14 @@ end
return false
end
end
length(a.defined) length(b.defined) || return false
n = length(b.defined)
length(a.undef) length(b.undef) || return false
n = length(b.undef)
ai = bi = 0
for i in 1:n
ai += a.defined[i]
bi += b.defined[i]
!a.defined[i] && b.defined[i] && return false
!b.defined[i] && continue
ai += !a.undef[i]
bi += !b.undef[i]
a.undef[i] && !b.undef[i] && return false
b.undef[i] && continue
# Field is defined for both `a` and `b`
af = a.fields[ai]
bf = b.fields[bi]
Expand Down Expand Up @@ -478,8 +478,8 @@ end
nf = nfields(a.val)
bi = 0
for i in 1:nf
!isdefined(a.val, i) && b.defined[i] && return false
!b.defined[i] && continue
!isdefined(a.val, i) && !b.undef[i] && return false
b.undef[i] && continue
bfᵢ = b.fields[bi += 1]
if i == nf
bfᵢ = unwrapva(bfᵢ)
Expand Down Expand Up @@ -550,7 +550,7 @@ end
if isa(a, PartialStruct)
isa(b, PartialStruct) || return false
length(a.fields) == length(b.fields) || return false
a.defined == b.defined || return false
a.undef == b.undef || return false
widenconst(a) == widenconst(b) || return false
a.fields === b.fields && return true # fast path
for i in 1:length(a.fields)
Expand Down Expand Up @@ -764,9 +764,9 @@ function Core.PartialStruct(::AbstractLattice, @nospecialize(typ), fields::Vecto
return PartialStruct(typ, fields)
end

function Core.PartialStruct(::AbstractLattice, @nospecialize(typ), defined::BitVector, fields::Vector{Any})
function Core.PartialStruct(::AbstractLattice, @nospecialize(typ), undef::BitVector, fields::Vector{Any})
for i = 1:length(fields)
assert_nested_slotwrapper(fields[i])
end
return Core._PartialStruct(typ, defined, fields)
return Core._PartialStruct(typ, undef, fields)
end
24 changes: 12 additions & 12 deletions Compiler/src/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -326,35 +326,35 @@ function n_initialized(t::Const)
return something(findfirst(i::Int->!isdefined(t.val,i), 1:nf), nf+1)-1
end

defined_fields(pstruct::PartialStruct) = pstruct.defined
defined_fields(pstruct::PartialStruct) = _bitvector(ntuple(i -> !pstruct.undef[i], length(pstruct.undef)))

function defined_field_index(pstruct::PartialStruct, fi)
i = 0
for iter in 1:fi
iter length(pstruct.defined) && pstruct.defined[iter] && (i += 1)
iter length(pstruct.undef) && !pstruct.undef[iter] && (i += 1)
end
i
end

get_defined_field(pstruct::PartialStruct, fi) = pstruct.fields[defined_field_index(pstruct, fi)]
is_field_defined(pstruct::PartialStruct, fi) = get(pstruct.defined, fi, false)
is_field_defined(pstruct::PartialStruct, fi) = !get(pstruct.undef, fi, true)

function define_field(pstruct::PartialStruct, fi, @nospecialize(ft))
n = length(pstruct.defined)
if fi n && pstruct.defined[fi]
n = length(pstruct.undef)
if fi n && !pstruct.undef[fi]
# XXX: merge new information?
# `setfield!(..., rand()); setfield!(..., 2.0)`
return nothing
end
defined = falses(max(fi, n))
undef = trues(max(fi, n))
for i in 1:n
defined[i] = pstruct.defined[i]
undef[i] = pstruct.undef[i]
end
fields = copy(pstruct.fields)
defined[fi] = true
undef[fi] = false
i = defined_field_index(pstruct, fi)
insert!(fields, i + 1, ft)
PartialStruct(fallback_lattice, pstruct.typ, defined, fields)
PartialStruct(fallback_lattice, pstruct.typ, undef, fields)
end

# needed while we are missing functions such as broadcasting or ranges
Expand Down Expand Up @@ -401,9 +401,9 @@ end
isa(typeb, Const) || isa(typeb, PartialStruct) || return false
@assert all(x & y == x for (x, y) in zip(defined_fields(typea), defined_fields(typeb))) "typeb ⊑ typea is assumed"
fi = 0
nf = length(typea.defined)
nf = length(typea.undef)
for i = 1:nf
typea.defined[i] || continue
!typea.undef[i] || continue
fi += 1
ai = unwrapva(typea.fields[fi])
bi = fieldtype(aty, i)
Expand Down Expand Up @@ -702,7 +702,7 @@ end
# handle that in the main loop above to get a more accurate type.
push!(fields, Vararg)
end
anyrefine && return PartialStruct(𝕃, aty, defined, fields)
anyrefine && return PartialStruct(𝕃, aty, _bitvector(ntuple(i -> !defined[i], length(defined))), fields)
end
return nothing
end
Expand Down
16 changes: 8 additions & 8 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4835,9 +4835,9 @@ let ⊑ = Compiler.partialorder(Compiler.fallback_lattice)
@test t ⊑ Union{Tuple{Bool,Bool},Tuple{Bool,Bool,Int}}

t = PartialStruct(𝕃, Tuple{Int, Int}, Any[Const(1), Int])
@test t.defined == [true, true]
@test t.undef == [false, false]
t = PartialStruct(𝕃, Partial, Any[String, Const(2)])
@test t.defined == [true, true, false]
@test t.undef == [false, false, true]
@test t ⊑ t && t ⊔ t === t

t1 = PartialStruct(𝕃, Partial, Any[String, Const(3)])
Expand All @@ -4846,19 +4846,19 @@ let ⊑ = Compiler.partialorder(Compiler.fallback_lattice)
t3 = t1 ⊔ t2
@test t3.fields == Any[String, Int]

t1 = PartialStruct(𝕃, Partial, BitVector([false, true, true]), Any[Int, Const(3)])
t1 = PartialStruct(𝕃, Partial, BitVector([true, false, false]), Any[Int, Const(3)])
@test t1 ⊑ t1 && t1 ⊔ t1 === t1
t2 = PartialStruct(𝕃, Partial, BitVector([true, false, true]), Any[Const("x"), Int])
t2 = PartialStruct(𝕃, Partial, BitVector([false, true, false]), Any[Const("x"), Int])
t3 = t1 ⊔ t2
@test t3.defined == [false, false, true] && t3.fields == Any[Int]
@test t3.undef == [true, true, false] && t3.fields == Any[Int]

t1 = PartialStruct(𝕃, Tuple, Any[Int, String, Vararg])
@test t1.defined == [true, true]
@test t1.undef == [false, false]
@test t1 ⊑ t1 && t1 ⊔ t1 == t1
t2 = PartialStruct(𝕃, Tuple, Any[Int, Any])
@test !(t1 ⊑ t2) && !(t2 ⊑ t1)
t3 = t1 ⊔ t2
@test t3.defined == [true, true] && t3.fields == Any[Int, Any]
@test t3.undef == [false, false] && t3.fields == Any[Int, Any]
t2 = PartialStruct(𝕃, Tuple, Any[Int, Any, Vararg])
@test t1 ⊑ t2
@test t1 ⊔ t2 === t2
Expand All @@ -4877,7 +4877,7 @@ let ⊑ = Compiler.partialorder(Compiler.fallback_lattice)
t = form_partially_defined_struct(Partial3, Const(:y))
@test t == PartialStruct(𝕃, Partial3, Any[Int, String])
t = form_partially_defined_struct(Partial3, Const(:z))
@test t == PartialStruct(𝕃, Partial3, BitVector([true, false, true]), Any[Int, Float64])
@test t == PartialStruct(𝕃, Partial3, BitVector([false, true, false]), Any[Int, Float64])
t = form_partially_defined_struct(t, Const(:y))
@test t == PartialStruct(𝕃, Partial3, Any[Int, String, Float64])
t = PartialStruct(𝕃, Partial3, Any[Int, String])
Expand Down
22 changes: 11 additions & 11 deletions base/coreir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Core.Const
"""
struct PartialStruct
typ
defined::BitVector # sorted list of fields that are known to be defined
undef::BitVector # represents whether a given field may be undefined
fields::Vector{Any} # i-th element describes the lattice element for the i-th defined field
end
Expand All @@ -24,16 +24,16 @@ some elements are known to be constants or a struct whose `Any`-typed field is i
with `Int` values.
- `typ` indicates the type of the object
- `defined` records which fields are defined
- `undef` records which fields are possibly undefined
- `fields` holds the lattice elements corresponding to each defined field of the object
If `typ` is a struct, `defined` represents whether the corresponding field of the struct is guaranteed to be
initialized. For any defined field (`defined[i] === true`), there is a corresponding `fields` element
If `typ` is a struct, `undef` represents whether the corresponding field of the struct is guaranteed to be
initialized. For any defined field (`undef[i] === false`), there is a corresponding `fields` element
which provides information about the type of the defined field.
If `typ` is a tuple, the last element of `fields` may be `Vararg`. In this case, it is
guaranteed that the number of elements in the tuple is at least `length(fields)-1`, but the
exact number of elements is unknown (`defined` then has a length of `length(fields)-1`).
exact number of elements is unknown (`undef` then has a length of `length(fields)-1`).
"""
Core.PartialStruct

Expand All @@ -44,21 +44,21 @@ function Core.PartialStruct(@nospecialize(typ), fields::Vector{Any})
(isa(t, UnionAll) || isa(t, Union)) && (t = argument_datatype(t))
nfields = isa(t, DataType) ? datatype_fieldcount(t) : nothing
if nfields === nothing || nfields == ndef
defined = trues(ndef)
undef = falses(ndef)
else
@assert nfields ndef
defined = falses(nfields)
undef = trues(nfields)
for i in 1:ndef
defined[i] = true
undef[i] = false
end
end
Core._PartialStruct(typ, defined, fields)
Core._PartialStruct(typ, undef, fields)
end

(==)(a::PartialStruct, b::PartialStruct) = a.typ === b.typ && a.defined == b.defined && a.fields == b.fields
(==)(a::PartialStruct, b::PartialStruct) = a.typ === b.typ && a.undef == b.undef && a.fields == b.fields

function Base.getproperty(pstruct::Core.PartialStruct, name::Symbol)
name === :defined && return getfield(pstruct, :defined)::BitVector
name === :undef && return getfield(pstruct, :undef)::BitVector
getfield(pstruct, name)
end

Expand Down
2 changes: 1 addition & 1 deletion src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3691,7 +3691,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_emptysvec, 0, 0, 1);

jl_partial_struct_type = jl_new_datatype(jl_symbol("PartialStruct"), core, jl_any_type, jl_emptysvec,
jl_perm_symsvec(3, "typ", "defined", "fields"),
jl_perm_symsvec(3, "typ", "undef", "fields"),
jl_svec(3, jl_any_type, jl_any_type, jl_array_any_type),
jl_emptysvec, 0, 0, 3);

Expand Down

0 comments on commit 8a9f31d

Please sign in to comment.