Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout of arrays #91

Closed
gnzlbg opened this issue Feb 21, 2019 · 14 comments
Closed

Layout of arrays #91

gnzlbg opened this issue Feb 21, 2019 · 14 comments
Labels
A-layout Topic: Related to data structure layout (`#[repr]`)

Comments

@gnzlbg
Copy link
Contributor

gnzlbg commented Feb 21, 2019

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

@RalfJung RalfJung added the A-layout Topic: Related to data structure layout (`#[repr]`) label Feb 22, 2019
@RalfJung
Copy link
Member

RalfJung commented Feb 22, 2019

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
Copy link
Contributor Author

gnzlbg commented Feb 22, 2019

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
Copy link
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
Copy link
Member

RalfJung commented Feb 22, 2019

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
Copy link
Member

Amanieu commented Feb 22, 2019

See rust-lang/rfcs#1397.

@RalfJung
Copy link
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
Copy link
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
Copy link
Contributor Author

gnzlbg commented Feb 22, 2019

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
Copy link
Member

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

@gnzlbg
Copy link
Contributor Author

gnzlbg commented Mar 6, 2019

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?

gnzlbg added a commit to gnzlbg/unsafe-code-guidelines that referenced this issue Mar 6, 2019
gnzlbg added a commit to gnzlbg/unsafe-code-guidelines that referenced this issue Mar 6, 2019
gnzlbg added a commit to gnzlbg/unsafe-code-guidelines that referenced this issue Mar 6, 2019
@gnzlbg gnzlbg mentioned this issue Mar 6, 2019
gnzlbg added a commit to gnzlbg/unsafe-code-guidelines that referenced this issue Mar 6, 2019
@RalfJung
Copy link
Member

RalfJung commented Mar 6, 2019

@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
Copy link

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
Copy link
Member

RalfJung commented Mar 6, 2019

@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
Copy link

hanna-kruppe commented Mar 6, 2019

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

gnzlbg added a commit that referenced this issue Mar 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-layout Topic: Related to data structure layout (`#[repr]`)
Projects
None yet
Development

No branches or pull requests

4 participants