-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Clarify cast rules, especially regarding fat pointers. #1052
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
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -319,20 +319,28 @@ descriptions are equivalent. | |
Casting is indicated by the `as` keyword. A cast `e as U` is valid if one of the | ||
following holds: | ||
|
||
* `e` has type `T` and `T` coerces to `U`; | ||
|
||
* `e` has type `*T` and `U` is `*U_0` (i.e., between any raw pointers); | ||
|
||
* `e` has type `*T` and `U` is `uint` , or vice versa; | ||
|
||
* `e` has type `T` and `T` and `U` are any numeric types; | ||
|
||
* `e` is a C-like enum and `U` is any integer type, `bool`; | ||
|
||
* `e` has type `T` and `T == u8` and `U == char`; | ||
|
||
* `e` has type `T` and `T == &[V, ..n]` or `T == &V` and `U == *const V`, and | ||
similarly for the mutable variants to either `*const V` or `*mut V`. | ||
* `e` has type `T` and `T` coerces to `U`; *coercion-cast* | ||
* `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or | ||
unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast* | ||
* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast* | ||
* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast* | ||
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* | ||
* `e` is a C-like enum and `U` is an integer type; *enum-cast* | ||
* `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast* | ||
* `e` has type `u8` and `U` is `char`; *u8-char-cast* | ||
* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast* | ||
* `e` is a function pointer type and `U` has type `*T`, | ||
while `T: Sized`; *fptr-ptr-cast* | ||
* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast* | ||
|
||
where `&.T` and `*T` are references of either mutability, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: the period in |
||
and where unsize_kind(`T`) is the kind of the unsize info | ||
in `T` - the vtable for a trait definition (e.g. `fmt::Display` or | ||
`Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`). | ||
|
||
Note that lengths are not adjusted when casting raw slices - | ||
`T: *const [u16] as *const [u8]` creates a slice that only includes | ||
half of the original memory. | ||
|
||
Casting is not transitive, that is, even if `e as U1 as U2` is a valid | ||
expression, `e as U2` is not necessarily so (in fact it will only be valid if | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
presumably the same holds
&mut [T;n]
and*T
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It didn't originally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason for the mut version not to be here? Feels to me it ought to be for the sake of completeness, unless there is a good reason not to.
Is it worth specifying what happens if n == 0 for this kind of cast? I assume the cast succeeds, but what is the value of the pointer? (null? undefined? a valid pointer to something?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nrc
I can't think of a reason to exclude
mut
here. After all, you can certainly do&mut foo[0] as *T
. Regarding 0, I think the answer is probably "an undefined value" (not UB) for the time being, but in general we actually are more limiting than you might think here. (Specifically, we have be careful because of zero-sized types; we used to usenull
more often, but often now useheap::EMPTY
, because of interactions with the null-pointer-optimizations and so forth. A specific example is escaping me at this moment.)