Skip to content

Commit 4cd1833

Browse files
committed
re-structure 'invalid values' enumeration to instead define what is *valid*
1 parent b1d1060 commit 4cd1833

File tree

1 file changed

+43
-30
lines changed

1 file changed

+43
-30
lines changed

src/behavior-considered-undefined.md

+43-30
Original file line numberDiff line numberDiff line change
@@ -59,33 +59,10 @@ Please read the [Rustonomicon] before writing unsafe code.
5959
* Executing code compiled with platform features that the current platform
6060
does not support (see [`target_feature`]), *except* if the platform explicitly documents this to be safe.
6161
* Calling a function with the wrong call ABI or unwinding from a function with the wrong unwind ABI.
62-
* Producing an invalid value, even in private fields and locals. "Producing" a
62+
* Producing an [invalid value][invalid-values]. "Producing" a
6363
value happens any time a value is assigned to or read from a place, passed to
6464
a function/primitive operation or returned from a function/primitive
6565
operation.
66-
The following values are invalid (at their respective type):
67-
* A value other than `false` (`0`) or `true` (`1`) in a [`bool`].
68-
* A discriminant in an `enum` not included in the type definition.
69-
* A null `fn` pointer.
70-
* A value in a `char` which is a surrogate or above `char::MAX`.
71-
* A `!` (all values are invalid for this type).
72-
* An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained
73-
from [uninitialized memory][undef], or uninitialized memory in a `str`.
74-
* A reference or `Box<T>` that is [dangling], misaligned, or points to an invalid value
75-
(in case of dynamically sized types, using the actual dynamic type of the
76-
pointee as determined by the metadata).
77-
* Invalid metadata in a wide reference, `Box<T>`, or raw pointer. The requirement
78-
for the metadata is determined by the type of the unsized tail:
79-
* `dyn Trait` metadata is invalid if it is not a pointer to a vtable for `Trait`.
80-
* Slice (`[T]`) metadata is invalid if the length is not a valid `usize`
81-
(i.e., it must not be read from uninitialized memory).
82-
Furthermore, for wide references and `Box<T>`, slice metadata is invalid
83-
if it makes the total size of the pointed-to value bigger than `isize::MAX`.
84-
* Invalid values for a type with a custom definition of invalid values.
85-
In the standard library, this affects [`NonNull<T>`] and [`NonZero*`].
86-
87-
> **Note**: `rustc` achieves this with the unstable
88-
> `rustc_layout_scalar_valid_range_*` attributes.
8966
* Incorrect use of inline assembly. For more details, refer to the [rules] to
9067
follow when writing code that uses inline assembly.
9168
* **In [const context](const_eval.md#const-context)**: transmuting or otherwise
@@ -94,11 +71,6 @@ Please read the [Rustonomicon] before writing unsafe code.
9471
'Reinterpreting' refers to loading the pointer value at integer type without a
9572
cast, e.g. by doing raw pointer casts or using a union.
9673

97-
**Note:** Uninitialized memory is also implicitly invalid for any type that has
98-
a restricted set of valid values. In other words, the only cases in which
99-
reading uninitialized memory is permitted are inside `union`s and in "padding"
100-
(the gaps between the fields/elements of a type).
101-
10274
> **Note**: Undefined behavior affects the entire program. For example, calling
10375
> a function in C that exhibits undefined behavior of C means your entire
10476
> program contains undefined behaviour that can also affect the Rust code. And
@@ -155,6 +127,46 @@ entire range, so it is important that the length metadata is never too large. In
155127
particular, the dynamic size of a Rust value (as determined by `size_of_val`)
156128
must never exceed `isize::MAX`.
157129

130+
### Invalid values
131+
[invalid-values]: #invalid-values
132+
133+
The Rust compiler assumes that all values produced during program execution are
134+
"valid", and producing an invalid value is hence immediate UB.
135+
136+
Whether a value is valid depends on the type:
137+
* A [`bool`] value must be `false` (`0`) or `true` (`1`).
138+
* A `fn` pointer value must be non-null.
139+
* A `char` value must not be a surrogate (i.e., must not be in the range `0xD800..=0xDFFF`) and must be equal to or less than `char::MAX`.
140+
* A `!` value must never exist.
141+
* An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer must be
142+
initialized, i.e., must not be obtained from [uninitialized memory][undef].
143+
* A `str` value is treated like `[u8]`, i.e. it must be initialized.
144+
* An `enum` must have a valid discriminant, and all fields of the variant indicated by that discriminant must be valid at their respective type.
145+
* A `struct`, tuple, and array requires all fields/elements to be valid at their respective type.
146+
* For a `union`, the exact validity requirements are not decided yet. The following is certain:
147+
* If the `union` has a zero-sized field, then all values are valid.
148+
* If a value is valid for a particular `union` field, then it is valid for the union.
149+
* A reference or [`Box<T>`] must be aligned, it cannot be [dangling], and it must point to a valid value
150+
(in case of dynamically sized types, using the actual dynamic type of the
151+
pointee as determined by the metadata).
152+
* The metadata of a wide reference, [`Box<T>`], or raw pointer must match
153+
the type of the unsized tail:
154+
* `dyn Trait` metadata must be a pointer to a compiler-generated vtable for `Trait`.
155+
* Slice (`[T]`) metadata must be a valid `usize`.
156+
Furthermore, for wide references and [`Box<T>`], slice metadata is invalid
157+
if it makes the total size of the pointed-to value bigger than `isize::MAX`.
158+
* If a type has a custom range of a valid values, then a valid value must be in that range.
159+
In the standard library, this affects [`NonNull<T>`] and [`NonZero<T>`].
160+
161+
> **Note**: `rustc` achieves this with the unstable
162+
> `rustc_layout_scalar_valid_range_*` attributes.
163+
164+
**Note:** Uninitialized memory is also implicitly invalid for any type that has
165+
a restricted set of valid values. In other words, the only cases in which
166+
reading uninitialized memory is permitted are inside `union`s and in "padding"
167+
(the gaps between the fields of a type).
168+
169+
158170
[`bool`]: types/boolean.md
159171
[`const`]: items/constant-items.md
160172
[noalias]: http://llvm.org/docs/LangRef.html#noalias
@@ -164,7 +176,8 @@ must never exceed `isize::MAX`.
164176
[`UnsafeCell<U>`]: ../std/cell/struct.UnsafeCell.html
165177
[Rustonomicon]: ../nomicon/index.html
166178
[`NonNull<T>`]: ../core/ptr/struct.NonNull.html
167-
[`NonZero*`]: ../core/num/index.html
179+
[`NonZero<T>`]: ../core/num/struct.NonZero.html
180+
[`Box<T>`]: ../alloc/boxed/struct.Box.html
168181
[place expression context]: expressions.md#place-expressions-and-value-expressions
169182
[rules]: inline-assembly.md#rules-for-inline-assembly
170183
[points to]: #pointed-to-bytes

0 commit comments

Comments
 (0)