Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/type-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,15 @@ The `Rust` representation is the default representation for nominal types withou
r[layout.repr.rust.layout]
The only data layout guarantees made by this representation are those required for soundness. These are:

1. The offset of a field is divisible by that field's alignment.
2. The alignment of the type is at least the maximum alignment of its fields.
1. The offset of a constructible field is divisible by that field's alignment.
2. The alignment of the type is at least the maximum alignment of its constructible fields.
3. For any constructible field, its offset plus its size is at most the size of the type.

r[layout.repr.rust.layout.constructible]

A field is considered constructible if it is possible to create a value of the type containing the field.
Copy link
Copy Markdown
Member

@tmandry tmandry Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A field is considered constructible if it is possible to create a value of the type containing the field.
A field is considered constructible if it is possible to create a value containing the field.

Below the type is E; there is no type E::B. So the next line doesn't follow from the existing definition.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

Suggested change
A field is considered constructible if it is possible to create a value of the type containing the field.
A field is considered constructible if it is part of an inhabited struct or enum variant, or part of a union.

Copy link
Copy Markdown
Member

@Nadrieril Nadrieril Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought speaking in terms of individual fields feels weird, e.g. I could imagine:

enum Foo {
  A { x: u32 },
  B { x: u32, y: ! },
}

and I could imagine (I kinda want even) that we add a language feature whereby we can write foo.x because that field exists in all variants. Is x constructible then? Well no because x refers to two "real" fields.

So I'd rather say: a type has space for its inhabited variants, and an inhabited variant has space for its fields.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think under this section of the reference, those xs have to be separate fields because otherwise a field might have multiple offsets, and this section talks about fields as if they have a single offset.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this definition isn't quite right, because in the example E is the type and you can create a value of that type, which would mean that y is still "constructible" because it's talking about type.

Perhaps this should be talking about variants instead? (At least in the compiler even structs have variants, just exactly one variant, so the reference might want to adopt that approach.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can create values of type E, but you can't create a value of type E that contains the field y.


For example, given `enum E { A { x: u32 }, B { y: u32, z: ! } }`, the field `x` is constructible because you can create the value `E::A { x: 0 }`, but the fields `y` and `z` are not constructible because the type of `z` is uninhabited, so it is impossible to create an `E::B` value.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems easier to define this as

  • all fields of a struct and union are constructible
  • for an enum, fields of a variant are constructible if all fields of that variant are inhabited

Is there a definition of "inhabited" we can refer to?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your proposed definition makes the guarantee apply to structs even if there are ! fields. But if a struct has a field of type !, surely none of the fields are constructible? It seems like changing the guarantee is a better fix than redefining constructible to mean something less natural.

Copy link
Copy Markdown
Member

@RalfJung RalfJung Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't realize you meant to exclude structs with uninhabited fields. I think we do want to guarantee that fields are disjoint and fit in the type even for such structs -- that seems pretty much settled to me.


r[layout.repr.rust.layout.struct]
For [structs], it is further guaranteed that the fields do not overlap. That is, the fields can be ordered such that the offset plus the size of any field is less than or equal to the offset of the next field in the ordering. The ordering does not have to be the same as the order in which the fields are specified in the declaration of the type.
Expand Down
Loading