Skip to content

Layout of arrays #91

Closed
Closed
@gnzlbg

Description

@gnzlbg
Contributor

We are missing the layout of arrays (I think we just forgot about this). Tangentially related to the layout of homogeneous structs: #36

Activity

added
A-layoutTopic: Related to data structure layout (`#[repr]`)
on Feb 22, 2019
RalfJung

RalfJung commented on Feb 22, 2019

@RalfJung
Member

I expect there is little controversy here: The first element is at offset 0, the stride is the element type size.

It'd be nice to eventually have types with stride > size (avoiding padding at the end), but I am not sure if that is realistic?

gnzlbg

gnzlbg commented on Feb 22, 2019

@gnzlbg
ContributorAuthor

It'd be nice to eventually have types with stride > size (avoiding padding at the end),

I'm not sure I follow, do you mean stride < size ?:

#[repr(align(4))] struct A([u8; 3]);  // size_of == 4
type B = [A; 4]; // size_of == 12 instead of 16 ?
RalfJung

RalfJung commented on Feb 22, 2019

@RalfJung
Member

I'm not sure I follow, do you mean stride < size ?:

No, that makes no sense. Then elements would overlap.
In your example, a mutable reference to two neiughboring elements of B would overlap.

I mean

struct A(u16, u8); // size == 3
type B = [A; 4]; // size == 16 because all elements need to be aligned
RalfJung

RalfJung commented on Feb 22, 2019

@RalfJung
Member

So to be clear, I think we should keep open the option of eventually having types where the size is not a multiple of the alignment, which implies that arrays of such types will have to have stride > size.

To that end, we should declare arrays as something like: The first element is at offset 0, and the stride of the array is computed as the size of the element type rounded up to the next multiple of the alignment of the element type.

Amanieu

Amanieu commented on Feb 22, 2019

@Amanieu
Member
RalfJung

RalfJung commented on Feb 22, 2019

@RalfJung
Member

@gnzlbg remarks that we should also state explicitly that since repr(C) types have a size that is a multiple of their alignment, for them, we'll always have stride == size. This ensures FFI compatibility.

RalfJung

RalfJung commented on Feb 22, 2019

@RalfJung
Member

@Amanieu thanks! The plan here is not to specify that this actually happens. but to word things in a way that it can happen in the future.

That RFC points out that this interacts with [T; 3] being the same as (T, T, T). Good point. Namely, the type could differ in that the tuple collapses its trailing padding but the array might not. So we should call out that the total size of the array might be either elem_stride * N or elem_stride*(N-1) + elem_size.

gnzlbg

gnzlbg commented on Feb 22, 2019

@gnzlbg
ContributorAuthor

Namely, the type could differ in that the tuple collapses its trailing padding but the array might not.

One of the many options that were proposed in #36 were that (T, T, T) should have the same layout as [T; 3]. Maybe we should call this out as an unresolved question (if we want to write something about arrays before that issue is resolved), or try to resolve both issues together.

RalfJung

RalfJung commented on Feb 22, 2019

@RalfJung
Member

For now I think we should just document how these decisions affect each other.

gnzlbg

gnzlbg commented on Mar 6, 2019

@gnzlbg
ContributorAuthor

Good point. Namely, the type could differ in that the tuple collapses its trailing padding but the array might not.

Does anybody have an example of such a type?

added 3 commits that reference this issue on Mar 6, 2019
b7c749d
8582d8f
0b4e710
added a commit that references this issue on Mar 6, 2019
6358eef
RalfJung

RalfJung commented on Mar 6, 2019

@RalfJung
Member

@gnzlbg

struct A(u16, u8); // size = 3
struct Homogeneous(A, A, A); // size = 4+4+3 = 11 because we avoid padding at the end
type Array = [A; 3]; // naively, size = 3*4 = 12
hanna-kruppe

hanna-kruppe commented on Mar 6, 2019

@hanna-kruppe

That would make sense if we made a distinction between "size" vs "stride" in the language, but we don't. As is, the size has to be a multiple of the alignment and trailing padding of fields can't be repurposed because anyone with a &mut T to the field is allowed to write size_of::<T>() bytes.

RalfJung

RalfJung commented on Mar 6, 2019

@RalfJung
Member

@rkruppe see above for the prior discussion where I basically argue we should be forwards-compatible with a world where size and stride can be different. I don't think this is fundamentally incompatible with mutable references.

There are some hard questions around using ptr::offset for indexing, though.

hanna-kruppe

hanna-kruppe commented on Mar 6, 2019

@hanna-kruppe

Ah, I see. I disagree, but I'll take that over to the PR.

added a commit that references this issue on Mar 14, 2019
c4c1859
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-layoutTopic: Related to data structure layout (`#[repr]`)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Amanieu@RalfJung@gnzlbg@hanna-kruppe

        Issue actions

          Layout of arrays · Issue #91 · rust-lang/unsafe-code-guidelines