From 4ba0917ec29b29aaa67943ea8e9cdd0c8938989e Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 8 Jul 2019 16:44:55 +0200 Subject: [PATCH 1/5] Guarantee that some structs are zero sized --- reference/src/layout/structs-and-tuples.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/reference/src/layout/structs-and-tuples.md b/reference/src/layout/structs-and-tuples.md index b7c55451..981b724b 100644 --- a/reference/src/layout/structs-and-tuples.md +++ b/reference/src/layout/structs-and-tuples.md @@ -122,6 +122,12 @@ compiler will not reorder it, to allow for the possibility of unsizing. E.g., `struct Foo { x: u16, y: u32 }` and `struct Foo { x: u16, y: T }` where `T = u32` are not guaranteed to be identical. +#### Zero-sized structs + +Structs with default layout are zero-sized, if they contain no fields of +non-zero size. That is, either the type has no fields, or all of its fields have +zero size. + #### Unresolved questions During the course of the discussion in [#11] and [#12], various @@ -131,15 +137,6 @@ issue has been opened for further discussion on the repository. This section documents the questions and gives a few light details, but the reader is referred to the issues for further discussion. -**Zero-sized structs ([#37]).** If you have a struct which -- -transitively -- contains no data of non-zero size, then the size of -that struct will be zero as well. These zero-sized structs appear -frequently as exceptions in other layout considerations (e.g., -single-field structs). An example of such a struct is -`std::marker::PhantomData`. - -[#37]: https://github.com/rust-rfcs/unsafe-code-guidelines/issues/37 - **Single-field structs ([#34]).** If you have a struct with single field (`struct Foo { x: T }`), should we guarantee that the memory layout of `Foo` is identical to the memory layout of `T` (note that ABI details From 6e4d2c3eda909cded25007e06c34d15c4f223544 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 8 Jul 2019 17:01:11 +0200 Subject: [PATCH 2/5] Add example --- reference/src/layout/structs-and-tuples.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/reference/src/layout/structs-and-tuples.md b/reference/src/layout/structs-and-tuples.md index 981b724b..627722cf 100644 --- a/reference/src/layout/structs-and-tuples.md +++ b/reference/src/layout/structs-and-tuples.md @@ -128,6 +128,20 @@ Structs with default layout are zero-sized, if they contain no fields of non-zero size. That is, either the type has no fields, or all of its fields have zero size. +For example, all these types are zero-sized: + +```rust +# use std::mem::size_of; +struct Zst0; +struct Zst1(Zst0); +struct Zst2(Zst1, Zst0); +# fn main() { +# assert_eq!(size_of::(), 0); +# assert_eq!(size_of::(), 0); +# assert_eq!(size_of::(), 0); +# } +``` + #### Unresolved questions During the course of the discussion in [#11] and [#12], various From c847771fbdacfa653ec9836df0d8436353966817 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 13 Jul 2019 12:11:01 +0200 Subject: [PATCH 3/5] Extend the guarantee to types with default layout but increased alignment --- reference/src/layout/structs-and-tuples.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/src/layout/structs-and-tuples.md b/reference/src/layout/structs-and-tuples.md index 627722cf..5e660a8c 100644 --- a/reference/src/layout/structs-and-tuples.md +++ b/reference/src/layout/structs-and-tuples.md @@ -124,15 +124,15 @@ x: u16, y: T }` where `T = u32` are not guaranteed to be identical. #### Zero-sized structs -Structs with default layout are zero-sized, if they contain no fields of -non-zero size. That is, either the type has no fields, or all of its fields have -zero size. +Structs with default layout or default layout with increased alignment are +zero-sized, if they contain no fields of non-zero size. That is, either the type +has no fields, or all of its fields have zero size. For example, all these types are zero-sized: ```rust # use std::mem::size_of; -struct Zst0; +#[repr(align(32))] struct Zst0; struct Zst1(Zst0); struct Zst2(Zst1, Zst0); # fn main() { From 0daf227f9dac0f7e8ebebd18f6a0b590f86ca63d Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 13 Jul 2019 12:24:32 +0200 Subject: [PATCH 4/5] Extend the guarantee to all struct types --- reference/src/layout/structs-and-tuples.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/reference/src/layout/structs-and-tuples.md b/reference/src/layout/structs-and-tuples.md index 5e660a8c..645311b6 100644 --- a/reference/src/layout/structs-and-tuples.md +++ b/reference/src/layout/structs-and-tuples.md @@ -124,16 +124,17 @@ x: u16, y: T }` where `T = u32` are not guaranteed to be identical. #### Zero-sized structs -Structs with default layout or default layout with increased alignment are -zero-sized, if they contain no fields of non-zero size. That is, either the type -has no fields, or all of its fields have zero size. +Structs with default layout (`repr(Rust)`), layout with increased alignment +(`repr(align(N))`), packed layout (`repr(packed(N))`), or C-compatible layout +(`repr(C)`) are zero-sized, if they contain no fields of non-zero size. That is, +either the type has no fields, or all of its fields have zero size. For example, all these types are zero-sized: ```rust # use std::mem::size_of; #[repr(align(32))] struct Zst0; -struct Zst1(Zst0); +#[repr(C)] struct Zst1(Zst0); struct Zst2(Zst1, Zst0); # fn main() { # assert_eq!(size_of::(), 0); From ac0cc9c04719bb2dd8e7b50c312b7fb6228a828e Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 26 Jul 2019 10:29:20 +0200 Subject: [PATCH 5/5] Reword guarantee --- reference/src/layout/structs-and-tuples.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/reference/src/layout/structs-and-tuples.md b/reference/src/layout/structs-and-tuples.md index 645311b6..652252e9 100644 --- a/reference/src/layout/structs-and-tuples.md +++ b/reference/src/layout/structs-and-tuples.md @@ -124,10 +124,8 @@ x: u16, y: T }` where `T = u32` are not guaranteed to be identical. #### Zero-sized structs -Structs with default layout (`repr(Rust)`), layout with increased alignment -(`repr(align(N))`), packed layout (`repr(packed(N))`), or C-compatible layout -(`repr(C)`) are zero-sized, if they contain no fields of non-zero size. That is, -either the type has no fields, or all of its fields have zero size. +For `repr(Rust)`, `repr(packed(N))`, `repr(align(N))`, and `repr(C)` +structs: if all fields of a struct have size 0, then the struct has size 0. For example, all these types are zero-sized: