Skip to content

Commit 773b7f6

Browse files
committed
Move pointer compatibility rules from footnote to pointer-to-pointer section
1 parent 5b3ca00 commit 773b7f6

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

src/expressions/operator-expr.md

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ reference types and `mut` or `const` in pointer types.
527527
| Enumeration | Integer type | [Enum cast][expr.as.enum] |
528528
| `bool` or `char` | Integer type | [Primitive to integer cast][expr.as.bool-char-as-int] |
529529
| `u8` | `char` | [`u8` to `char` cast][expr.as.u8-as-char] |
530-
| `*T` | `*V` [^meta-compat] | [Pointer to pointer cast][expr.as.pointer] |
530+
| `*T` | `*V` (when [compatible][expr.as.pointer]) | [Pointer to pointer cast][expr.as.pointer] |
531531
| `*T` where `T: Sized` | Integer type | [Pointer to address cast][expr.as.pointer-as-int] |
532532
| Integer type | `*V` where `V: Sized` | [Address to pointer cast][expr.as.int-as-pointer] |
533533
| `&m₁ [T; n]` | `*m₂ T` [^lessmut] | Array to pointer cast |
@@ -539,13 +539,6 @@ reference types and `mut` or `const` in pointer types.
539539
| [Function pointer] | Integer | Function pointer to address cast |
540540
| Closure [^no-capture] | Function pointer | Closure to function pointer cast |
541541

542-
[^meta-compat]: where `T` and `V` have compatible metadata:
543-
* `V: Sized`, or
544-
* Both slice metadata (`*[u16]` -> `*[u8]`, `*str` -> `*(u8, [u32])`), or
545-
* Both the same trait object metadata, modulo dropping auto traits (`*dyn Debug` -> `*(u16, dyn Debug)`, `*dyn Debug + Send` -> `*dyn Debug`)
546-
* **Note**: *adding* auto traits is only allowed if the principal trait has the auto trait as a super trait (given `trait T: Send {}`, `*dyn T` -> `*dyn T + Send` is valid, but `*dyn Debug` -> `*dyn Debug + Send` is not)
547-
* **Note**: Generics (including lifetimes) must match (`*dyn T<'a, A>` -> `*dyn T<'b, B>` requires `'a = 'b` and `A = B`)
548-
549542
[^lessmut]: only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference/pointer to
550543
`const` pointer is allowed.
551544

@@ -737,18 +730,29 @@ r[expr.as.pointer.behavior]
737730
r[expr.as.pointer.sized]
738731
- If `T` and `U` are both sized, the pointer is returned unchanged.
739732

733+
r[expr.as.pointer.discard-metadata]
734+
- 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+
740736
r[expr.as.pointer.unsized]
741737
- If `T` and `U` are both unsized, the pointer is also returned unchanged.
742738
In particular, the metadata is preserved exactly.
739+
The cast can only be performed if the metadata is compatible according to the below rules:
743740

744-
For instance, a cast from `*const [T]` to `*const [U]` preserves the number of elements.
745-
Note that, as a consequence, such casts do not necessarily preserve the size of the pointer's referent
746-
(e.g., casting `*const [u16]` to `*const [u8]` will result in a raw pointer which refers to an object of half the size of the original).
747-
The same holds for `str` and any compound type whose unsized tail is a slice type,
748-
such as `struct Foo(i32, [u8])` or `(u64, Foo)`.
741+
r[expr.as.pointer.unsized.slice]
742+
- When `T` and `U` are unsized with slice metadata, they are always compatible.
743+
The metadata of a slice is the number of elements, so casting `*[u16] -> *[u8]` is legal but will result in reducing the number of bytes by half.
749744

750-
r[expr.as.pointer.discard-metadata]
751-
- 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.
745+
r[expr.as.pointer.unsized.trait]
746+
- When `T` and `U` are unsized with trait object metadata, the metadata is compatible only when all of the following holds:
747+
1. The principal trait must be the same. (you can't cast from `dyn Foo` to `dyn Bar`)
748+
2. Auto traits may be removed, but not added. (you can cast `dyn Foo + Send` to `dyn Foo`, but the opposite is not legal)
749+
3. Trailing lifetimes may be changed. (you can cast `dyn Foo + 'a` to `dyn Foo + 'b` for any `'a`,`'b`)
750+
4. Generics (including lifetimes) and associated types must match exactly. (`*dyn T<'a, A>` -> `*dyn T<'b, B>` requires `'a = 'b` and `A = B`)
751+
752+
Note that [trait upcasting][coerce.unsize.trait-upcast] (including the addition of auto traits) requires a coercion and is not supported by `as` casts.
753+
754+
r[expr.as.pointer.unsized.compound]
755+
- When `T` or `U` is a struct or tuple type whose last field is unsized, it has the same metadata and compatibility rules as its last field.
752756

753757
r[expr.assign]
754758
## Assignment expressions

0 commit comments

Comments
 (0)