You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/expressions/operator-expr.md
+19-15Lines changed: 19 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -527,7 +527,7 @@ reference types and `mut` or `const` in pointer types.
527
527
| Enumeration | Integer type |[Enum cast][expr.as.enum]|
528
528
|`bool` or `char`| Integer type |[Primitive to integer cast][expr.as.bool-char-as-int]|
529
529
|`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]|
531
531
|`*T` where `T: Sized`| Integer type |[Pointer to address cast][expr.as.pointer-as-int]|
532
532
| Integer type |`*V` where `V: Sized`|[Address to pointer cast][expr.as.int-as-pointer]|
533
533
|`&m₁ [T; n]`|`*m₂ T`[^lessmut]| Array to pointer cast |
@@ -539,13 +539,6 @@ reference types and `mut` or `const` in pointer types.
539
539
|[Function pointer]| Integer | Function pointer to address cast |
540
540
| Closure [^no-capture]| Function pointer | Closure to function pointer cast |
541
541
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
-
549
542
[^lessmut]: only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference/pointer to
550
543
`const` pointer is allowed.
551
544
@@ -737,18 +730,29 @@ r[expr.as.pointer.behavior]
737
730
r[expr.as.pointer.sized]
738
731
- If `T` and `U` are both sized, the pointer is returned unchanged.
739
732
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
+
740
736
r[expr.as.pointer.unsized]
741
737
- If `T` and `U` are both unsized, the pointer is also returned unchanged.
742
738
In particular, the metadata is preserved exactly.
739
+
The cast can only be performed if the metadata is compatible according to the below rules:
743
740
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.
749
744
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.
0 commit comments