Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify semantics of the various pointer to pointer casts #1451

Merged
merged 3 commits into from
Feb 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,15 +478,20 @@ unsafe {
assert_eq!(values[1], 3);
```

#### Slice DST pointer to pointer cast
#### Pointer-to-pointer cast

For slice types like `[T]` and `[U]`, the raw pointer types `*const [T]`, `*mut [T]`,
`*const [U]`, and `*mut [U]` encode the number of elements in this slice. Casts between
these raw pointer types preserve the number of elements. Note that, as a consequence,
such casts do *not* necessarily preserve the size of the pointer's referent (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). The same holds for `str` and any compound type
whose unsized tail is a slice type, such as struct `Foo(i32, [u8])` or `(u64, Foo)`.
`*const T` / `*mut T` can be cast to `*const U` / `*mut U` with the following behavior:

- If `T` and `U` are both sized, the pointer is returned unchanged.
- If `T` and `U` are both unsized, the pointer is also returned unchanged.
In particular, the metadata is preserved exactly.

For instance, a cast from `*const [T]` to `*const [U]` preserves the number of elements.
Note that, as a consequence, such casts do not necessarily preserve the size of the pointer's referent
(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).
The same holds for `str` and any compound type whose unsized tail is a slice type,
such as `struct Foo(i32, [u8])` or `(u64, Foo)`.
- 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.

## Assignment expressions

Expand Down Expand Up @@ -687,3 +692,17 @@ See [this test] for an example of using this dependency.
[_TypeNoBounds_]: ../types.md#type-expressions
[_RangeExpression_]: ./range-expr.md
[_UnderscoreExpression_]: ./underscore-expr.md

<script>
(function() {
var fragments = {
"#slice-dst-pointer-to-pointer-cast": "operator-expr.html#pointer-to-pointer-cast",
};
var target = fragments[window.location.hash];
if (target) {
var url = window.location.toString();
var base = url.substring(0, url.lastIndexOf('/'));
window.location.replace(base + "/" + target);
}
})();
</script>