Skip to content

Commit 3b3e36e

Browse files
authored
Update values.rst
1 parent 9605ee0 commit 3b3e36e

File tree

1 file changed

+39
-3
lines changed

1 file changed

+39
-3
lines changed

src/coding-guidelines/values.rst

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,42 @@ Values
5252
5353
let x: u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB
5454
55+
.. compliant_example::
56+
:id: compl_ex_Ke869nSXuShZ
57+
:status: draft
58+
59+
This compliant example contains no undefined behavior because all of the bytes in ``Newtype32`` are defined by ``Uninit32``.
60+
Creating an uninitialized union is allowed, if somewhat controversial.
61+
When bytes are read as a type (e.g., by using
62+
`ptr.read() <https://doc.rust-lang.org/std/ptr/fn.read.html>`_,
63+
`*ptr <https://doc.rust-lang.org/std/ptr/index.html>`_, or
64+
`mem::transmute <https://doc.rust-lang.org/std/mem/fn.transmute.html>`_), a *typed read* occurs.
65+
The typed read asserts the bytes are valid as that type.
66+
A union's validity requirement is the union of its variants' validity requirements.
67+
Because ``()`` is zero-sized, it has no validity requirements.
68+
A ``union`` containing ``()`` can validly hold any bit pattern, including uninitialized bytes.
69+
``Uninit32`` and ``MaybeUninit`` are both unions with ``()`` as a possibility.
70+
This means they must be valid to read from a blob of uninitialized bytes within a valid allocation.
71+
Because ``Newtype32`` is entirely defined by ``Uninit32``, it is also valid to read from uninitialized bytes.
72+
The ``struct`` wrapper does not impose additional validity requirements.
73+
74+
.. code-block:: rust
75+
76+
use std::mem::MaybeUninit;
77+
78+
union Uninit32 {
79+
u: u32,
80+
i: i32,
81+
f: f32,
82+
void: (),
83+
}
84+
85+
struct Newtype32(Uninit32);
86+
87+
fn main() {
88+
let x: Newtype32 = unsafe { MaybeUninit::uninit().assume_init() };
89+
}
90+
5591
.. non_compliant_example::
5692
:id: non_compl_ex_eJDxk4PP63DF
5793
:status: draft
@@ -102,9 +138,9 @@ Values
102138
:id: non_compl_ex_bHaxZM7JOY0k
103139
:status: draft
104140

105-
Creating an uninitialized union value is allowed, if somewhat controversial.
106-
However, all the of any read field must have been initialized by a prior write and
141+
Any read field must have been initialized by a prior write and
107142
the bytes written must form a valid representation for the field's type.
143+
Reading ``x.u`` as a ``u32`` field is undefined behavior because the memory is uninitialized.
108144

109145
.. code-block:: rust
110146
@@ -171,7 +207,7 @@ Values
171207
:id: compl_ex_Xr6MjsqshHxc
172208
:status: draft
173209

174-
The following code reads a union field:
210+
The following code reads a ``union`` field:
175211

176212
.. code-block:: rust
177213

0 commit comments

Comments
 (0)