Skip to content

Commit e9ebd56

Browse files
committed
Define pointer metadata
The pointer-to-pointer cast rules and the wide-pointer validity rule both speak of the *metadata* of a pointer, but we hadn't explicitly defined the term (even though we had defined the contents of that metadata). Let's do that and link to it.
1 parent 2c27905 commit e9ebd56

3 files changed

Lines changed: 10 additions & 8 deletions

File tree

src/behavior-considered-undefined.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ r[undefined.dangling.zero-size]
100100
If the [size is 0][zero-sized], then the pointer is trivially never "dangling" (even if it is a null pointer).
101101

102102
r[undefined.dangling.dynamic-size]
103-
Note that dynamically sized types (such as slices and strings) point to their entire range, so it is important that the length metadata is never too large.
103+
Note that dynamically sized types (such as slices and strings) point to their entire range, so it is important that the length [metadata] is never too large.
104104

105105
r[undefined.dangling.alloc-limit]
106106
In particular, the dynamic size of a Rust value (as determined by `size_of_val`) must never exceed `isize::MAX`, since it is impossible for a single allocation to be larger than `isize::MAX`.
@@ -142,10 +142,10 @@ r[undefined.validity.union]
142142
* For a `union`, the exact validity requirements are not decided yet. Obviously, all values that can be created entirely in safe code are valid. If the union has a [zero-sized] field, then every possible value is valid. Further details are [still being debated](https://github.com/rust-lang/unsafe-code-guidelines/issues/438).
143143

144144
r[undefined.validity.reference-box]
145-
* A reference or [`Box<T>`] must be aligned and non-null, it cannot be [dangling], and it must point to a valid value (in case of dynamically sized types, using the actual dynamic type of the pointee as determined by the metadata). Note that the last point (about pointing to a valid value) remains a subject of some debate.
145+
* A reference or [`Box<T>`] must be aligned and non-null, it cannot be [dangling], and it must point to a valid value (in case of dynamically sized types, using the actual dynamic type of the pointee as determined by the [metadata]). Note that the last point (about pointing to a valid value) remains a subject of some debate.
146146

147147
r[undefined.validity.wide]
148-
* The metadata of a wide reference, [`Box<T>`], or raw pointer must match the type of the unsized tail:
148+
* The [metadata] of a wide reference, [`Box<T>`], or raw pointer must match the type of the unsized tail:
149149
* `dyn Trait` metadata must be a pointer to a compiler-generated vtable for `Trait`. (For raw pointers, this requirement remains a subject of some debate.)
150150
* Slice (`[T]`) metadata must be a valid `usize`. Furthermore, for wide references and [`Box<T>`], slice metadata is invalid if it makes the total size of the pointed-to value bigger than `isize::MAX`.
151151

@@ -156,7 +156,7 @@ r[undefined.validity.valid-range]
156156
> `rustc` achieves this with the unstable `rustc_layout_scalar_valid_range_*` attributes.
157157
158158
r[undefined.validity.const-provenance]
159-
* **In [const contexts]**: In addition to what is described above, further provenance-related requirements apply during const evaluation. Any value that holds pure integer data (the `i*`/`u*`/`f*` types as well as `bool` and `char`, enum discriminants, and slice metadata) must not carry any provenance. Any value that holds pointer data (references, raw pointers, function pointers, and `dyn Trait` metadata) must either carry no provenance, or all bytes must be fragments of the same original pointer value in the correct order.
159+
* **In [const contexts]**: In addition to what is described above, further provenance-related requirements apply during const evaluation. Any value that holds pure integer data (the `i*`/`u*`/`f*` types as well as `bool` and `char`, enum discriminants, and slice [metadata]) must not carry any provenance. Any value that holds pointer data (references, raw pointers, function pointers, and `dyn Trait` metadata) must either carry no provenance, or all bytes must be fragments of the same original pointer value in the correct order.
160160

161161
This implies that transmuting or otherwise reinterpreting a pointer (reference, raw pointer, or function pointer) into a non-pointer type (such as integers) is undefined behavior if the pointer had provenance.
162162

@@ -194,6 +194,7 @@ r[undefined.validity.undef]
194194
[`target_feature`]: attributes/codegen.md#the-target_feature-attribute
195195
[`UnsafeCell<U>`]: std::cell::UnsafeCell
196196
[Rustonomicon]: ../nomicon/index.html
197+
[metadata]: dynamic-sized.pointer-types
197198
[`NonNull<T>`]: core::ptr::NonNull
198199
[`NonZero<T>`]: core::num::NonZero
199200
[place expression context]: expressions.md#place-expressions-and-value-expressions

src/dynamically-sized-types.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ r[dynamic-sized.restriction]
88
Such types can only be used in certain cases:
99

1010
r[dynamic-sized.pointer-types]
11-
* [Pointer types] to <abbr title="dynamically sized types">DSTs</abbr> are sized but have twice the size of pointers to sized types
12-
* Pointers to slices and `str` also store the number of elements.
13-
* Pointers to trait objects also store a pointer to a vtable.
11+
* [Pointer types] to <abbr title="dynamically sized types">DSTs</abbr> are sized but have twice the size of pointers to sized types, since they also store *metadata*:
12+
* Pointers to slices store the number of elements; pointers to `str` store the length in bytes.
13+
* Pointers to trait objects store a pointer to a vtable.
1414

1515
r[dynamic-sized.question-sized]
1616
* <abbr title="dynamically sized types">DSTs</abbr> can be provided as type arguments to generic type parameters having the special `?Sized` bound. They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound. By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`.

src/expressions/operator-expr.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ r[expr.as.pointer.sized]
732732
> ```
733733
734734
r[expr.as.pointer.discard-metadata]
735-
- If `T` is unsized and `U` is sized, the cast discards all metadata that completes the wide pointer `T` and produces a thin pointer `U` consisting of the data part of the unsized pointer.
735+
- If `T` is unsized and `U` is sized, the cast discards all [metadata] that completes the wide pointer `T` and produces a thin pointer `U` consisting of the data part of the unsized pointer.
736736
737737
> [!EXAMPLE]
738738
> ```rust
@@ -1244,6 +1244,7 @@ As with normal assignment expressions, compound assignment expressions always pr
12441244
[logical not]: ../types/boolean.md#logical-not
12451245
[logical or]: ../types/boolean.md#logical-or
12461246
[logical xor]: ../types/boolean.md#logical-xor
1247+
[metadata]: dynamic-sized.pointer-types
12471248
[moved from]: expr.move.movable-place
12481249
[mutable]: ../expressions.md#mutability
12491250
[place expression]: ../expressions.md#place-expressions-and-value-expressions

0 commit comments

Comments
 (0)