From 280fe42486560e871222404629c5e0d3eda3b639 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 8 Jul 2019 15:55:14 +0200 Subject: [PATCH 01/17] Guarantee the default layout of unions with a single field --- reference/src/layout/unions.md | 96 +++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 13 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 86fc3edc..e01ca36a 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -6,29 +6,99 @@ not to change until an RFC ratifies them. [#13]: https://github.com/rust-rfcs/unsafe-code-guidelines/issues/13 -The only degree of freedom the compiler has when computing the layout of a union -like +### Layout of individual union fields -```rust,ignore -union U { f1: T1, f2: T2 } +The layout of each union field is determined by its type. + +
Rationale + +This is required to allow creating references to union fields: + +```rust +# fn main() { unsafe { +# #[derive(Copy, Clone)] +struct T1; +union U { f1: T1 } +let u = U { f1: T1 }; +let t1: &T1 = &u.f1; +// &T1 works for all references +# }} ``` +
-is to determine the offset of the fields. The layout of these fields themselves -is already entirely determined by their types, and since we intend to allow -creating references to fields (`&u.f1`), unions do not have any wiggle-room -there. +### Unions with default layout ("`repr(Rust)`") -### Default layout ("repr rust") +**The default layout of unions is**, in general, **not specified.** -**The default layout of unions is not specified.** As of this writing, we want -to keep the option of using non-zero offsets open for the future; whether this -is useful depends on what exactly the compiler-assumed invariants about union -contents are. +
Rationale + +As of this writing, we want to keep the option of using non-zero offsets open +for the future; whether this is useful depends on what exactly the +compiler-assumed invariants about union contents are. This might become clearer +after the validity of unions +([unsafe-code-guidelines/73](https://github.com/rust-lang/unsafe-code-guidelines/issues/73)) +is settled. Even if the offsets happen to be all 0, there might still be differences in the function call ABI. If you need to pass unions by-value across an FFI boundary, you have to use `#[repr(C)]`. +
+ +#### Layout of unions with a single non-zero-sized field + +The layout of unions with a single non-zero-sized field is the same as the +layout of that field if: + +* that field has no padding bits, and +* the alignment requirement of all zero-sized fields is 1. + +For example, here: + +```rust +# use std::mem::{size_of, align_of}; +# #[derive(Copy, Clone)] +#[repr(transparent)] +struct SomeStruct(i32); +# #[derive(Copy, Clone)] +struct Zst; +union U0 { + f0: SomeStruct, + f1: Zst, +} +# fn main() { +# assert_eq!(size_of::(), size_of::()); +# assert_eq!(align_of::(), align_of::()); +# } +``` + +the union `U0` has the same layout as `SomeStruct`, because `SomeStruct` has no +padding bits - it is equivalent to an `i32` due to `repr(transparent)` - and +because the alignment of `Zst` is 1. + +On the other hand, here: + +```rust +# use std::mem::{size_of, align_of}; +# #[derive(Copy, Clone)] +struct SomeOtherStruct(i32); +# #[derive(Copy, Clone)] +#[repr(align(16))] struct Zst2; +union U1 { + f0: SomeOtherStruct, + f1: Zst2, +} +# fn main() { +# assert_eq!(size_of::(), align_of::()); +# assert_eq!(align_of::(), align_of::()); +assert_eq!(align_of::(), 16); +# } +``` + +the alignment requirement of `Zst2` is not 1, and `SomeOtherStruct` has an +unspecified layout and could contain padding bits. Therefore, the layout of `U1` +is **unspecified**. + ### C-compatible layout ("repr C") The layout of `repr(C)` unions follows the C layout scheme. Per sections From fb9ad78379c3ac3399a8d01f14056a728905b50c Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Aug 2019 08:03:53 +0200 Subject: [PATCH 02/17] Use picture to explain union layout --- reference/src/layout/unions.md | 41 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index e01ca36a..5db6af8e 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -8,27 +8,36 @@ not to change until an RFC ratifies them. ### Layout of individual union fields -The layout of each union field is determined by its type. - -
Rationale +When laying out an `union`, the compiler has to decide how the fields of the +union are arranged. Union fields are laid out by the compiler "on top" of each +other, that is, the bytes of one field might overlap with the bytes of another +field - as opposed to, e.g., `struct`s, where the fields are laid out "next to" +each other, such that the bytes of one field never overlap with the bytes of +another field. This can be visualized as follows: + +```rust,ignore +[ P P [field0_ty] P P P P ] +[ P P P P [field1_ty] P P ] +[ P P P [field2_ty] P P P ] +``` -This is required to allow creating references to union fields: +> **Figure: union field layout**: Each row in the picture shows the layout of +> the union for each of its fields, where the square brackets `[]` depict an +> array of bytes. Here, `P` is a byte of type `Pad` and `[field{i}_ty]` is the +> bytes of the type of the `i`-th union field. -```rust -# fn main() { unsafe { -# #[derive(Copy, Clone)] -struct T1; -union U { f1: T1 } -let u = U { f1: T1 }; -let t1: &T1 = &u.f1; -// &T1 works for all references -# }} -``` -
+The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by +the field's layout. The compiler picks the offset of the fields with respect to +the union and the `union` size according to certain constraints like, for +example, the alignment requirements of the fields, the `#[repr]` attribute of +the `union`, etc. ### Unions with default layout ("`repr(Rust)`") -**The default layout of unions is**, in general, **not specified.** +The default layout of Rust unions is **unspecified**. + +That is, there are no guarantees about the offset of the fields, whether all +fields have the same offset, etc.
Rationale From 5b3aa2f03fa00692c38310a5d4ede913bb6b9908 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Aug 2019 08:11:06 +0200 Subject: [PATCH 03/17] Use 1-ZST terminology --- reference/src/layout/unions.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 5db6af8e..97dc5356 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -34,10 +34,11 @@ the `union`, etc. ### Unions with default layout ("`repr(Rust)`") -The default layout of Rust unions is **unspecified**. +Except for the guarantees provided below for some specific cases, the default +layout of Rust unions is, _in general_, **unspecified**. -That is, there are no guarantees about the offset of the fields, whether all -fields have the same offset, etc. +That is, there are no _general_ guarantees about the offset of the fields, +whether all fields have the same offset, etc.
Rationale @@ -59,8 +60,8 @@ you have to use `#[repr(C)]`. The layout of unions with a single non-zero-sized field is the same as the layout of that field if: -* that field has no padding bits, and -* the alignment requirement of all zero-sized fields is 1. +* all zero-sized fields are [1-ZST], and +* the non-zero sized field has no padding bits. For example, here: @@ -83,7 +84,7 @@ union U0 { the union `U0` has the same layout as `SomeStruct`, because `SomeStruct` has no padding bits - it is equivalent to an `i32` due to `repr(transparent)` - and -because the alignment of `Zst` is 1. +because `Zst` is a [1-ZST]. On the other hand, here: @@ -104,9 +105,10 @@ assert_eq!(align_of::(), 16); # } ``` -the alignment requirement of `Zst2` is not 1, and `SomeOtherStruct` has an -unspecified layout and could contain padding bits. Therefore, the layout of `U1` -is **unspecified**. +the layout of `U1` is **unspecified** because: + +* `Zst2` is not a [1-ZST], and +* `SomeOtherStruct` has an unspecified layout and could contain padding bits. ### C-compatible layout ("repr C") @@ -172,3 +174,5 @@ with no fields. When such types are used as an union field in C++, a "naive" translation of that code into Rust will not produce a compatible result. Refer to the [struct chapter](structs-and-tuples.md#c-compatible-layout-repr-c) for further details. + +[1-ZST]: ../glossary.md#zero-sized-type--zst From 7bb174385dbc3dd1af741b29d08ed8a305050916 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Aug 2019 13:15:57 +0200 Subject: [PATCH 04/17] Reword --- reference/src/layout/unions.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 97dc5356..0862270b 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -8,12 +8,12 @@ not to change until an RFC ratifies them. ### Layout of individual union fields -When laying out an `union`, the compiler has to decide how the fields of the -union are arranged. Union fields are laid out by the compiler "on top" of each -other, that is, the bytes of one field might overlap with the bytes of another -field - as opposed to, e.g., `struct`s, where the fields are laid out "next to" -each other, such that the bytes of one field never overlap with the bytes of -another field. This can be visualized as follows: +The main degree of freedom the compiler has when computing the layout of a union +is to determine the offset of the fields. Union fields are laid out by the +compiler "on top" of each other, that is, the bytes of one field might overlap +with the bytes of another field - as opposed to, e.g., `struct`s, where the +fields are laid out "next to" each other, such that the bytes of one field never +overlap with the bytes of another field. This can be visualized as follows: ```rust,ignore [ P P [field0_ty] P P P P ] From 58c5694047b36b481551ab3bc3db7ec7bb2d6466 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Aug 2019 13:35:09 +0200 Subject: [PATCH 05/17] Reword more --- reference/src/layout/unions.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 0862270b..c93cc5ab 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -8,12 +8,16 @@ not to change until an RFC ratifies them. ### Layout of individual union fields -The main degree of freedom the compiler has when computing the layout of a union -is to determine the offset of the fields. Union fields are laid out by the -compiler "on top" of each other, that is, the bytes of one field might overlap -with the bytes of another field - as opposed to, e.g., `struct`s, where the -fields are laid out "next to" each other, such that the bytes of one field never -overlap with the bytes of another field. This can be visualized as follows: +A union consists of several variants, one for each field. These variants are +laid out "on top" of each other, so they must all have the same size. That is, +the byte of each variant overlaps with the byte located at the same offset in +all other variants, and the bytes of one field might overlap with the bytes of +another field - as opposed to, e.g., `struct`s, where the fields are laid out +"next to" each other, such that the bytes of one field never overlap with the +bytes of another field. The main degree of freedom the compiler has when +computing the layout of a union is to pick where in its variant each field is +situated, i.e., the compiler picks the gap (often called padding) before and +after each field. This can be visualized as follows: ```rust,ignore [ P P [field0_ty] P P P P ] From 36bc3b60d8ddeab84dd20cfa46140d925e0db71a Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 27 Aug 2019 17:20:45 +0200 Subject: [PATCH 06/17] Use <---> for padding in pictures --- reference/src/layout/unions.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index c93cc5ab..ae0e2494 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -20,15 +20,15 @@ situated, i.e., the compiler picks the gap (often called padding) before and after each field. This can be visualized as follows: ```rust,ignore -[ P P [field0_ty] P P P P ] -[ P P P P [field1_ty] P P ] -[ P P P [field2_ty] P P P ] +[ <--> [field0_ty] <----> ] +[ <----> [field1_ty] <--> ] +[ <---> [field2_ty] <---> ] ``` > **Figure: union field layout**: Each row in the picture shows the layout of > the union for each of its fields, where the square brackets `[]` depict an -> array of bytes. Here, `P` is a byte of type `Pad` and `[field{i}_ty]` is the -> bytes of the type of the `i`-th union field. +> array of bytes, `<-...->` denotes different amount of padding, and +> `[field{i}_ty]` is the bytes of the type of the `i`-th union field. The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by the field's layout. The compiler picks the offset of the fields with respect to From 6502c2d54d7a2f8b6b63b25a498b6b78d48a897d Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 27 Aug 2019 17:28:57 +0200 Subject: [PATCH 07/17] Summarzie text --- reference/src/layout/unions.md | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index ae0e2494..c41333cc 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -8,16 +8,9 @@ not to change until an RFC ratifies them. ### Layout of individual union fields -A union consists of several variants, one for each field. These variants are -laid out "on top" of each other, so they must all have the same size. That is, -the byte of each variant overlaps with the byte located at the same offset in -all other variants, and the bytes of one field might overlap with the bytes of -another field - as opposed to, e.g., `struct`s, where the fields are laid out -"next to" each other, such that the bytes of one field never overlap with the -bytes of another field. The main degree of freedom the compiler has when -computing the layout of a union is to pick where in its variant each field is -situated, i.e., the compiler picks the gap (often called padding) before and -after each field. This can be visualized as follows: +A union consists of several variants, one for each field. All variants have the +same size and start at the same memory address, such that in memory the variants +overlap. This can be visualized as follows: ```rust,ignore [ <--> [field0_ty] <----> ] @@ -31,10 +24,11 @@ after each field. This can be visualized as follows: > `[field{i}_ty]` is the bytes of the type of the `i`-th union field. The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by -the field's layout. The compiler picks the offset of the fields with respect to -the union and the `union` size according to certain constraints like, for -example, the alignment requirements of the fields, the `#[repr]` attribute of -the `union`, etc. +the field's layout. The only degrees of freedom the compiler has when computing +the layout of a union are the size of the union and the offset of each union +field within its variant. How these are picked depends on certain constraints, +lik for example, the alignment requirements of the fields, the `#[repr]` +attribute of the `union`, etc. ### Unions with default layout ("`repr(Rust)`") From 080d63e4ab7340edd901970931051b77bab71648 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 27 Aug 2019 17:29:49 +0200 Subject: [PATCH 08/17] Clarify size of union --- reference/src/layout/unions.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index c41333cc..53d9c524 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -25,10 +25,11 @@ overlap. This can be visualized as follows: The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by the field's layout. The only degrees of freedom the compiler has when computing -the layout of a union are the size of the union and the offset of each union -field within its variant. How these are picked depends on certain constraints, -lik for example, the alignment requirements of the fields, the `#[repr]` -attribute of the `union`, etc. +the layout of a union are the size of the union, which can be larger than the +size of its largest field, and the offset of each union field within its +variant. How these are picked depends on certain constraints, lik for example, +the alignment requirements of the fields, the `#[repr]` attribute of the +`union`, etc. ### Unions with default layout ("`repr(Rust)`") From 83e9f3ddec6787f0ed623b8579bb4fc0f4c418f2 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 27 Aug 2019 17:35:16 +0200 Subject: [PATCH 09/17] Hyperlink all the things --- reference/src/glossary.md | 1 + reference/src/layout/unions.md | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/reference/src/glossary.md b/reference/src/glossary.md index be9f7a66..2e70d7bf 100644 --- a/reference/src/glossary.md +++ b/reference/src/glossary.md @@ -171,6 +171,7 @@ Accordingly, we say that a library (or an individual function) is *sound* if it Conversely, the library/function is *unsound* if safe code *can* cause Undefined Behavior. #### Layout +[layout]: #layout The *layout* of a type defines its size and alignment as well as the offsets of its subobjects (e.g. fields of structs/unions/enum/... or elements of arrays). Moreover, the layout of a type records its *function call ABI* (or just *ABI* for short): how the type is passed *by value* across a function boundary. diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 53d9c524..b0eecaa5 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -12,7 +12,7 @@ A union consists of several variants, one for each field. All variants have the same size and start at the same memory address, such that in memory the variants overlap. This can be visualized as follows: -```rust,ignore +```text [ <--> [field0_ty] <----> ] [ <----> [field1_ty] <--> ] [ <---> [field2_ty] <---> ] @@ -20,16 +20,19 @@ overlap. This can be visualized as follows: > **Figure: union field layout**: Each row in the picture shows the layout of > the union for each of its fields, where the square brackets `[]` depict an -> array of bytes, `<-...->` denotes different amount of padding, and +> array of bytes, `<-...->` denotes different amount of [padding], and > `[field{i}_ty]` is the bytes of the type of the `i`-th union field. The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by -the field's layout. The only degrees of freedom the compiler has when computing -the layout of a union are the size of the union, which can be larger than the -size of its largest field, and the offset of each union field within its -variant. How these are picked depends on certain constraints, lik for example, -the alignment requirements of the fields, the `#[repr]` attribute of the -`union`, etc. +the field's [layout]. The only degrees of freedom the compiler has when +computing the layout of a union are the size of the union, which can be larger +than the size of its largest field, and the offset of each union field within +its variant. How these are picked depends on certain constraints like, for +example, the alignment requirements of the fields, the `#[repr]` attribute of +the `union`, etc. + +[padding]: ../glossary.md#padding +[layout]: ../glossary.md#layout ### Unions with default layout ("`repr(Rust)`") From ccce61652f66101800743d2413bab55d19dbf7d9 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 10:15:40 +0200 Subject: [PATCH 10/17] Ralf feedback --- reference/src/layout/unions.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index b0eecaa5..b9eb2995 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -18,10 +18,10 @@ overlap. This can be visualized as follows: [ <---> [field2_ty] <---> ] ``` -> **Figure: union field layout**: Each row in the picture shows the layout of -> the union for each of its fields, where the square brackets `[]` depict an -> array of bytes, `<-...->` denotes different amount of [padding], and -> `[field{i}_ty]` is the bytes of the type of the `i`-th union field. +**Figure 1** (union-field layout): Each row in the picture shows the layout of +the union for each of its variants. The `<-...->` and `[ ... ]` denote the +differently-sized gaps and fields, respectively and the `[field{i}_ty]` are the +bytes of the type of the `i`-th union field. The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by the field's [layout]. The only degrees of freedom the compiler has when @@ -59,11 +59,8 @@ you have to use `#[repr(C)]`. #### Layout of unions with a single non-zero-sized field -The layout of unions with a single non-zero-sized field is the same as the -layout of that field if: - -* all zero-sized fields are [1-ZST], and -* the non-zero sized field has no padding bits. +The layout of unions with a single single non-[1-ZST]-field" is the same as the +layout of that field if it has no [padding] bytes. For example, here: From bf307b6a591c896cab39270aeb08b5274bfc947c Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 10:16:53 +0200 Subject: [PATCH 11/17] Remove redundant statement --- reference/src/layout/unions.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index b9eb2995..aae8d38f 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -20,8 +20,7 @@ overlap. This can be visualized as follows: **Figure 1** (union-field layout): Each row in the picture shows the layout of the union for each of its variants. The `<-...->` and `[ ... ]` denote the -differently-sized gaps and fields, respectively and the `[field{i}_ty]` are the -bytes of the type of the `i`-th union field. +differently-sized gaps and fields, respectively. The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by the field's [layout]. The only degrees of freedom the compiler has when From 55ab41682070428de13931a70f8e3b5455aabfde Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 10:24:57 +0200 Subject: [PATCH 12/17] Remove empty line --- reference/src/layout/unions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index aae8d38f..53948506 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -17,7 +17,6 @@ overlap. This can be visualized as follows: [ <----> [field1_ty] <--> ] [ <---> [field2_ty] <---> ] ``` - **Figure 1** (union-field layout): Each row in the picture shows the layout of the union for each of its variants. The `<-...->` and `[ ... ]` denote the differently-sized gaps and fields, respectively. From 88c91f09ff2a08a0a3abd154ec13511ec21e3347 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 10:25:53 +0200 Subject: [PATCH 13/17] Update reference/src/layout/unions.md Co-Authored-By: Ralf Jung --- reference/src/layout/unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 53948506..fbb0d063 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -105,7 +105,7 @@ assert_eq!(align_of::(), 16); the layout of `U1` is **unspecified** because: * `Zst2` is not a [1-ZST], and -* `SomeOtherStruct` has an unspecified layout and could contain padding bits. +* `SomeOtherStruct` has an unspecified layout and could contain padding bytes. ### C-compatible layout ("repr C") From 4d777f193cf745dcbb9ada0c317feab4012b42a3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 10:27:00 +0200 Subject: [PATCH 14/17] Update reference/src/layout/unions.md Co-Authored-By: Ralf Jung --- reference/src/layout/unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index fbb0d063..f3fe8c8a 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -57,7 +57,7 @@ you have to use `#[repr(C)]`. #### Layout of unions with a single non-zero-sized field -The layout of unions with a single single non-[1-ZST]-field" is the same as the +The layout of unions with a single non-[1-ZST]-field" is the same as the layout of that field if it has no [padding] bytes. For example, here: From f18d4a9a301058142453a3dbfa96e16073a07837 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 12:28:37 +0200 Subject: [PATCH 15/17] Clarify dofs, fix link --- reference/src/layout/unions.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index f3fe8c8a..79906e14 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -22,12 +22,12 @@ the union for each of its variants. The `<-...->` and `[ ... ]` denote the differently-sized gaps and fields, respectively. The individual fields (`[field{i}_ty_]`) are blocks of fixed size determined by -the field's [layout]. The only degrees of freedom the compiler has when -computing the layout of a union are the size of the union, which can be larger -than the size of its largest field, and the offset of each union field within -its variant. How these are picked depends on certain constraints like, for -example, the alignment requirements of the fields, the `#[repr]` attribute of -the `union`, etc. +the field's [layout]. Since we allow creating references to union fields +(`&u.i`), the only degrees of freedom the compiler has when computing the layout +of a union are the size of the union, which can be larger than the size of its +largest field, and the offset of each union field within its variant. How these +are picked depends on certain constraints like, for example, the alignment +requirements of the fields, the `#[repr]` attribute of the `union`, etc. [padding]: ../glossary.md#padding [layout]: ../glossary.md#layout @@ -45,14 +45,14 @@ whether all fields have the same offset, etc. As of this writing, we want to keep the option of using non-zero offsets open for the future; whether this is useful depends on what exactly the compiler-assumed invariants about union contents are. This might become clearer -after the validity of unions -([unsafe-code-guidelines/73](https://github.com/rust-lang/unsafe-code-guidelines/issues/73)) -is settled. +after the validity of unions [#73] is settled. Even if the offsets happen to be all 0, there might still be differences in the function call ABI. If you need to pass unions by-value across an FFI boundary, you have to use `#[repr(C)]`. +[#73]: https://github.com/rust-lang/unsafe-code-guidelines/issues/73 +
#### Layout of unions with a single non-zero-sized field From a64942461a6dde8d85f69d5f38f000c15954f946 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 28 Aug 2019 13:37:57 +0200 Subject: [PATCH 16/17] Update reference/src/layout/unions.md Co-Authored-By: Ralf Jung --- reference/src/layout/unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 79906e14..87fa2834 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -45,7 +45,7 @@ whether all fields have the same offset, etc. As of this writing, we want to keep the option of using non-zero offsets open for the future; whether this is useful depends on what exactly the compiler-assumed invariants about union contents are. This might become clearer -after the validity of unions [#73] is settled. +after the [validity of unions][#73] is settled. Even if the offsets happen to be all 0, there might still be differences in the function call ABI. If you need to pass unions by-value across an FFI boundary, From 6b544f31a475d3fc2deb447c41cfc7e8456fb345 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 29 Aug 2019 09:14:28 +0200 Subject: [PATCH 17/17] Update reference/src/layout/unions.md --- reference/src/layout/unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/layout/unions.md b/reference/src/layout/unions.md index 87fa2834..b9f018b4 100644 --- a/reference/src/layout/unions.md +++ b/reference/src/layout/unions.md @@ -38,7 +38,7 @@ Except for the guarantees provided below for some specific cases, the default layout of Rust unions is, _in general_, **unspecified**. That is, there are no _general_ guarantees about the offset of the fields, -whether all fields have the same offset, etc. +whether all fields have the same offset, what the call ABI of the union is, etc.
Rationale