From c3d23c2c7b4d88abeaed965327b9806d3d7c812a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Dec 2018 14:33:25 +0100 Subject: [PATCH 01/10] unions have no active field --- src/items/unions.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index b51f17461..164273a8a 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -29,18 +29,22 @@ struct types, except that it must specify exactly one field: let u = MyUnion { f1: 1 }; ``` -The expression above creates a value of type `MyUnion` with active field `f1`. -Active field of a union can be accessed using the same syntax as struct fields: +The expression above creates a value of type `MyUnion` and initializes the +storage using field `f1`. The union can be accessed using the same syntax as +struct fields: ```rust,ignore let f = u.f1; ``` -Inactive fields can be accessed as well (using the same syntax) if they are -sufficiently layout compatible with the current value kept by the union. -Reading incompatible fields results in undefined behavior. However, the active -field is not generally known statically, so all reads of union fields have to -be placed in `unsafe` blocks. +Unions have no notion of an "active field". Instead, every union access just +interprets the storage at the type of the field used for the access. The effect +of reading a union with a different field than it was written to is that of +calling [`transmute`]. Reading data at a bad type results in undefined behavior +(for example, reading the value `3` at type `bool`). + +However, which fields are safe to read and which not is generally not known +statically, so all reads of union fields have to be placed in `unsafe` blocks. ```rust # union MyUnion { f1: u32, f2: f32 } @@ -65,9 +69,9 @@ Commonly, code using unions will provide safe wrappers around unsafe union field accesses. Another way to access union fields is to use pattern matching. Pattern matching -on union fields uses the same syntax as struct patterns, except that the -pattern must specify exactly one field. Since pattern matching accesses -potentially inactive fields it has to be placed in `unsafe` blocks as well. +on union fields uses the same syntax as struct patterns, except that the pattern +must specify exactly one field. Since pattern matching is like reading the union +with a particular field, it has to be placed in `unsafe` blocks as well. ```rust # union MyUnion { f1: u32, f2: f32 } @@ -149,3 +153,4 @@ in [RFC 1897 "Unions v1.2"](https://github.com/rust-lang/rfcs/pull/1897). [_Generics_]: items/generics.html [_WhereClause_]: items/generics.html#where-clauses [_StructFields_]: items/structs.html +[`transmute`]: ../../std/mem/fn.transmute.html From 20922ac7d7a1971c2f68d20d4d3408d06641555e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Dec 2018 15:36:35 +0100 Subject: [PATCH 02/10] improve wording --- src/items/unions.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index 164273a8a..bd655e2ed 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -38,13 +38,12 @@ let f = u.f1; ``` Unions have no notion of an "active field". Instead, every union access just -interprets the storage at the type of the field used for the access. The effect -of reading a union with a different field than it was written to is that of -calling [`transmute`]. Reading data at a bad type results in undefined behavior -(for example, reading the value `3` at type `bool`). - -However, which fields are safe to read and which not is generally not known -statically, so all reads of union fields have to be placed in `unsafe` blocks. +interprets the storage at the type of the field used for the access. Reading a +union field is equivalent to a [`transmute`]: The data in the union, no matter +how it was stored there, is transmuted to the type if the field. Reading data +at a bad type results in undefined behavior (for example, reading the value `3` +at type `bool`). For this reason, all reads of union fields have to be placed +in `unsafe` blocks: ```rust # union MyUnion { f1: u32, f2: f32 } From 224303dd088b6dd27aeafde023560d151c38e406 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Dec 2018 15:38:13 +0100 Subject: [PATCH 03/10] typo --- src/items/unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/unions.md b/src/items/unions.md index bd655e2ed..a61fefbb1 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -40,7 +40,7 @@ let f = u.f1; Unions have no notion of an "active field". Instead, every union access just interprets the storage at the type of the field used for the access. Reading a union field is equivalent to a [`transmute`]: The data in the union, no matter -how it was stored there, is transmuted to the type if the field. Reading data +how it was stored there, is transmuted to the type of the field. Reading data at a bad type results in undefined behavior (for example, reading the value `3` at type `bool`). For this reason, all reads of union fields have to be placed in `unsafe` blocks: From 31352405cdf39879aa288e3a0a42c18dbe318790 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Dec 2018 08:53:54 +0100 Subject: [PATCH 04/10] remove reference to unaccepted RFC --- src/items/unions.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index a61fefbb1..8c6236c56 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -145,9 +145,6 @@ aspects of Rust language (such as privacy, name resolution, type inference, generics, trait implementations, inherent implementations, coherence, pattern checking, etc etc etc). -More detailed specification for unions, including unstable bits, can be found -in [RFC 1897 "Unions v1.2"](https://github.com/rust-lang/rfcs/pull/1897). - [IDENTIFIER]: identifiers.html [_Generics_]: items/generics.html [_WhereClause_]: items/generics.html#where-clauses From 3793103b72d6b6787bf026c8695d59d6860b3b2d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Dec 2018 08:57:08 +0100 Subject: [PATCH 05/10] clairification --- src/items/unions.md | 10 ++++++---- src/types/union.md | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index 8c6236c56..be627c4df 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -40,10 +40,12 @@ let f = u.f1; Unions have no notion of an "active field". Instead, every union access just interprets the storage at the type of the field used for the access. Reading a union field is equivalent to a [`transmute`]: The data in the union, no matter -how it was stored there, is transmuted to the type of the field. Reading data -at a bad type results in undefined behavior (for example, reading the value `3` -at type `bool`). For this reason, all reads of union fields have to be placed -in `unsafe` blocks: +how it was stored there, is transmuted to the type of the field. Just like with +any other transmute, it is the programmer's responsibility to make sure that the +data is valid for the field type. Failing to do so results in undefined +behavior (for example, reading the value `3` at type `bool` is undefined +behavior). For this reason, all reads of union fields have to be placed in +`unsafe` blocks: ```rust # union MyUnion { f1: u32, f2: f32 } diff --git a/src/types/union.md b/src/types/union.md index 68f851549..de7e720a2 100644 --- a/src/types/union.md +++ b/src/types/union.md @@ -3,10 +3,10 @@ A *union type* is a nominal, heterogeneous C-like union, denoted by the name of a [`union` item]. -A union contains the value of any one of its fields. Since the accessing the -wrong field can cause unexpected or undefined behaviour, `unsafe` is required -to read from a union field or to write to a field that doesn't implement -[`Copy`]. +A union access transmutes the content of the union to the type of the accessed +field. Since transmutes can cause unexpected or undefined behaviour, `unsafe` is +required to read from a union field or to write to a field that doesn't +implement [`Copy`]. The memory layout of a `union` is undefined by default, but the `#[repr(...)]` attribute can be used to fix a layout. From f1995cd8f57419693ae6d4320ed12b0080d5390b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Dec 2018 15:23:28 +0100 Subject: [PATCH 06/10] no more double space --- src/items/unions.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index be627c4df..5d8db00bb 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -30,21 +30,21 @@ let u = MyUnion { f1: 1 }; ``` The expression above creates a value of type `MyUnion` and initializes the -storage using field `f1`. The union can be accessed using the same syntax as +storage using field `f1`. The union can be accessed using the same syntax as struct fields: ```rust,ignore let f = u.f1; ``` -Unions have no notion of an "active field". Instead, every union access just -interprets the storage at the type of the field used for the access. Reading a +Unions have no notion of an "active field". Instead, every union access just +interprets the storage at the type of the field used for the access. Reading a union field is equivalent to a [`transmute`]: The data in the union, no matter -how it was stored there, is transmuted to the type of the field. Just like with +how it was stored there, is transmuted to the type of the field Just like with any other transmute, it is the programmer's responsibility to make sure that the -data is valid for the field type. Failing to do so results in undefined +data is valid for the field type. Failing to do so results in undefined behavior (for example, reading the value `3` at type `bool` is undefined -behavior). For this reason, all reads of union fields have to be placed in +behavior). For this reason, all reads of union fields have to be placed in `unsafe` blocks: ```rust From f85beb55dcb7cd7f325cd9c7271f9c0295b73d6a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Dec 2018 15:23:58 +0100 Subject: [PATCH 07/10] typos --- src/items/unions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index 5d8db00bb..eaf84e244 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -40,9 +40,9 @@ let f = u.f1; Unions have no notion of an "active field". Instead, every union access just interprets the storage at the type of the field used for the access. Reading a union field is equivalent to a [`transmute`]: The data in the union, no matter -how it was stored there, is transmuted to the type of the field Just like with +how it was stored there, is transmuted to the type of the field. Just like with any other transmute, it is the programmer's responsibility to make sure that the -data is valid for the field type. Failing to do so results in undefined +data is valid at the field's type. Failing to do so results in undefined behavior (for example, reading the value `3` at type `bool` is undefined behavior). For this reason, all reads of union fields have to be placed in `unsafe` blocks: From 9f9313fe39746152ee080085fbf3f8e4c191a07f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Dec 2018 15:38:52 +0100 Subject: [PATCH 08/10] improve wording --- src/items/unions.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index eaf84e244..7dd28d5e6 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -39,13 +39,14 @@ let f = u.f1; Unions have no notion of an "active field". Instead, every union access just interprets the storage at the type of the field used for the access. Reading a -union field is equivalent to a [`transmute`]: The data in the union, no matter -how it was stored there, is transmuted to the type of the field. Just like with -any other transmute, it is the programmer's responsibility to make sure that the -data is valid at the field's type. Failing to do so results in undefined -behavior (for example, reading the value `3` at type `bool` is undefined -behavior). For this reason, all reads of union fields have to be placed in -`unsafe` blocks: +union field reads the bits of the union at the field's type. It is the +programmer's responsibility to make sure that the data is valid at that +type. Failing to do so results in undefined behavior (for example, reading the +value `3` at type `bool` is undefined behavior). Effectively, writing to and +then reading from a union is equivalent to a [`transmute`] from the type used +for writing to the type used for reading. + +Consequently, all reads of union fields have to be placed in `unsafe` blocks: ```rust # union MyUnion { f1: u32, f2: f32 } From 9ecb58d1f0915038f5a7c844b7e31c85c7f81d2d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 27 Dec 2018 16:46:46 +0100 Subject: [PATCH 09/10] de-parenthesize --- src/items/unions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index 7dd28d5e6..010b73631 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -41,10 +41,10 @@ Unions have no notion of an "active field". Instead, every union access just interprets the storage at the type of the field used for the access. Reading a union field reads the bits of the union at the field's type. It is the programmer's responsibility to make sure that the data is valid at that -type. Failing to do so results in undefined behavior (for example, reading the -value `3` at type `bool` is undefined behavior). Effectively, writing to and -then reading from a union is equivalent to a [`transmute`] from the type used -for writing to the type used for reading. +type. Failing to do so results in undefined behavior. For example, reading the +value `3` at type `bool` is undefined behavior. Effectively, writing to and then +reading from a union is equivalent to a [`transmute`] from the type used for +writing to the type used for reading. Consequently, all reads of union fields have to be placed in `unsafe` blocks: From 7276ea775e636fc31f105e7fcc7994b4bfe17815 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 9 Jan 2019 13:27:41 +0100 Subject: [PATCH 10/10] s/equivalent/analogous/ --- src/items/unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/unions.md b/src/items/unions.md index 010b73631..43dc720cc 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -43,7 +43,7 @@ union field reads the bits of the union at the field's type. It is the programmer's responsibility to make sure that the data is valid at that type. Failing to do so results in undefined behavior. For example, reading the value `3` at type `bool` is undefined behavior. Effectively, writing to and then -reading from a union is equivalent to a [`transmute`] from the type used for +reading from a union is analogous to a [`transmute`] from the type used for writing to the type used for reading. Consequently, all reads of union fields have to be placed in `unsafe` blocks: