Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upClarify cast rules, especially regarding fat pointers. #1052
Conversation
nrc
self-assigned this
Apr 10, 2015
petrochenkov
reviewed
Apr 10, 2015
| @@ -321,18 +321,26 @@ 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`, `U` is `*U_0`, and either `U_0: Sized` or | |||
| unsize_kind(`T`) = unsize_kind(`U_0`); | |||
This comment has been minimized.
This comment has been minimized.
petrochenkov
Apr 10, 2015
Contributor
I.e. a fat pointer (*const Trait) can be truncated to thin pointer (*const u8)? I don't think it should be done with as. Fat pointers definitely should have some methods for extracting their components without shady transmutes, but as should convert only between pointers of the same kind IMO.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
petrochenkov
Apr 10, 2015
Contributor
I see that it's legal, it's written clearly, I don't understand why it should be legal.
This comment has been minimized.
This comment has been minimized.
arielb1
Apr 10, 2015
Author
Contributor
It throws away the DST info - that's a perfectly good cast (same as u32 -> u8).
This comment has been minimized.
This comment has been minimized.
petrochenkov
Apr 10, 2015
Contributor
My point is that as is one of the most overloaded entities in the language and now you are throwing even more semantics into it without sufficient reasons. Ideally even u32 -> u8 would be done with a specialized method, like truncate() and not with omnipotent as.
nrc
reviewed
Apr 10, 2015
|
|
||
| * `e` has type `*T` and `U` is `uint` , or vice versa; | ||
| * `e` has type `*T` and `U` is `usize`, or vice versa, while `T: Sized`; |
This comment has been minimized.
This comment has been minimized.
nrc
Apr 10, 2015
Member
I think we can also allow casts from *T to usize where T is unsized (it's not clear if that is what you meant or not)
This comment has been minimized.
This comment has been minimized.
arielb1
Apr 10, 2015
Author
Contributor
I meant for them not to be allowed. I can change this, through.
nrc
reviewed
Apr 10, 2015
|
|
||
| * `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 `U` is `*T`, and `e` is a mutable reference |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nrc
Apr 10, 2015
Member
I think this is too lax as stated, we should not allow &T to *U for arbitrary T and U
This comment has been minimized.
This comment has been minimized.
arielb1
Apr 10, 2015
Author
Contributor
Here e and U must be references to the same type (I used T in both places).
nrc
reviewed
Apr 10, 2015
| * `e` has type `&.T` and `U` is `*T`, and `e` is a mutable reference | ||
| if `U` is. | ||
|
|
||
| * `e` has type `&.[T; n]` and `U` is `*T`, and `e` is a mutable |
This comment has been minimized.
This comment has been minimized.
nrc
reviewed
Apr 10, 2015
|
|
||
| where `&.T` and `*T` are references of either mutability, | ||
| and where unsize_kind(`T`) is the kind of the unsize info | ||
| in `T` - a vtable or a length (or `()` if `T: Sized`). |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
LGTM! |
This comment has been minimized.
This comment has been minimized.
|
Are bool -> numeric casts ( |
This comment has been minimized.
This comment has been minimized.
|
Assume we have an empty slice or an empty array:
They are perfectly safe per se, but what does happen when we cast them to pointers?
As a result |
This comment has been minimized.
This comment has been minimized.
|
You can also do |
This comment has been minimized.
This comment has been minimized.
|
Yeah, I see, |
This comment has been minimized.
This comment has been minimized.
|
Anyway, do we want to allow usize/ptr -> fn casts? They are not currently allowed and not in any rule. |
This comment has been minimized.
This comment has been minimized.
|
I guess they are disallowed because |
This comment has been minimized.
This comment has been minimized.
|
Questions remaining: |
This comment has been minimized.
This comment has been minimized.
I think yes, but there are valid reasons for no
no this should at the least be a double cast usize -> ptr -> fn (but see below)
I'm not sure about how/if this should work, ping @nikomatsakis for an opinion
yes, they should be, it's often useful and is C-like |
This comment has been minimized.
This comment has been minimized.
|
Also, there is a char -> integer cast, which is also allowed |
This comment has been minimized.
This comment has been minimized.
|
Today's rustc allows fn -> usize, fn -> *ptr casts. Also, it allows ptr -> any int casts, which are used rather often. |
This comment has been minimized.
This comment has been minimized.
I think this should remain illegal, for the reason that @petrochenkov highlighted. That is, casts into safe types like |
This comment has been minimized.
This comment has been minimized.
|
but fn -> thin ptr/usize casts should be legal (they are, currently). |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 right, that seems ok to me. |
This comment has been minimized.
This comment has been minimized.
|
I notice that we actually allow casting of raw pointers to and from any integral type, not just usize. I expect this is not what we intend (and of course its backwards incompatible). Does anyone think we should be allow to do this? |
This comment has been minimized.
This comment has been minimized.
|
IMO, the conversions to/from any integral type except for |
This comment has been minimized.
This comment has been minimized.
|
liblibc defines |
arielb1
force-pushed the
arielb1:rfc-401-fix
branch
from
50899d3
to
bbceaa3
Apr 20, 2015
This comment has been minimized.
This comment has been minimized.
|
@arielb1 |
This comment has been minimized.
This comment has been minimized.
|
liblibc does this a lot, through. And I think changing |
This comment has been minimized.
This comment has been minimized.
|
Another way is to postulate that Update: making |
This comment has been minimized.
This comment has been minimized.
|
I now have something that works. |
pnkfelix
reviewed
Jun 2, 2015
| 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, |
This comment has been minimized.
This comment has been minimized.
pnkfelix
reviewed
Jun 2, 2015
|
|
||
| where `&.T` and `*T` are references of either mutability, | ||
| and where unsize_kind(`T`) is the kind of the unsize info | ||
| in `T` - a vtable or a length (or `()` if `T: Sized`). |
This comment has been minimized.
This comment has been minimized.
pnkfelix
Jun 2, 2015
Member
There are potentially two ways to interpret this "definition" for unsize_kind ... either:
unsize_kindsays whether the type is a trait, or a slice, or a sized type (i.e. there are only three possible values that it returns), orunsize_kindsays the same thing but also includes which trait (i.e. which vtable) for the first case, and which particular length for the second case (i.e. that its a much larger range of potential values).
I infer that the intention is the latter; i.e. that it is not legal e.g. to cast from one trait-object to another with an unrelated vtable via as, nor is it legal to cast from one array to another with a different length. But it still would be nice if the text didn't require any thinking on this point.
Anyway, I wouldn't block this change based on this detail; we can always come up with a later PR to try to clarify this later.
This comment has been minimized.
This comment has been minimized.
I also took the latter interpretation. |
This comment has been minimized.
This comment has been minimized.
|
Our interpretation was the former (iirc). If you're casting its up to you to ensure you aren't doing something stupid. |
This comment has been minimized.
This comment has been minimized.
|
Hmm. I'm getting a bit worried about this trait casting point. In particular, if we permit |
This comment has been minimized.
This comment has been minimized.
|
Hmm, based on the outstanding questions concerning trait object casts and |
This comment has been minimized.
This comment has been minimized.
|
We discussed a bit further on IRC, we agreed that while casting pointer to array seems reasonable, we couldn't come up with a good use case for casting trait objects. I propose we disallow casting trait objects entirely. We allow casts from |
This comment has been minimized.
This comment has been minimized.
|
I realize now that my note, or at least my inferred interpretation, did not make much sense.
(I suppose we might consider at least lint-warning that
|
This comment has been minimized.
This comment has been minimized.
|
@arielb1 As the RFC author, do you have any thoughts on the last minute back-and-forth on the details of trait-objects and It seems like this RFC is likely to be accepted with amendments, but I am not sure whether you would prefer to make such amendments yourself, or if you are okay with the person doing the merge doing such amendments, or if you in fact disagree with the proposed amendments? |
This comment has been minimized.
This comment has been minimized.
|
I am not sure casts between arrays of different types should try to compensate for the length difference - the sizes can be non-multiples of each-other, making it unclear which way the rounding should go. I expect raw fat pointer casting to be used in the same way as raw thin pointer casting - i.e., the pointer will either be cast back to the right type before being used, or the cast-type is sufficiently representation-equivalent to the expr-type (e.g. casting I am fine with making the vtable kind include the trait id (i.e. being |
This comment has been minimized.
This comment has been minimized.
|
I feel pretty strongly that we should not permit I'm of two minds about the slice casts. It's hard for me to imagine a scenario where it makes sense to do the cast unless the sizes are equal -- this is a bit different from |
This comment has been minimized.
This comment has been minimized.
|
An actual case for casting things of different sizes? I don't think there is really any, but we don't know the sizes at typeck time of course. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 for casting |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 I can easily imagine converting e.g. to |
This comment has been minimized.
This comment has been minimized.
|
to be clear, I don't really have a problem with allowing |
This comment has been minimized.
This comment has been minimized.
|
So it seems to be me that everyone is roughly on the same page that:
Is this an accurate summary? If so, @arielb1, would you prefer to edit the text appropriately, or should I do so when merging? |
This comment has been minimized.
This comment has been minimized.
|
Changed. |
This comment has been minimized.
This comment has been minimized.
|
It's official... the language subteam has decided to accept this RFC. |
This comment has been minimized.
This comment has been minimized.
|
It seems that there is at least some impl work remaining here, in that the compiler currently accepts a bit too much, at least with regard to object casts (though I see trans errors, which is nice): |
nikomatsakis
referenced this pull request
Jun 18, 2015
Closed
Clarify cast rules (tracking issue for RFC 1052) #26391
This comment has been minimized.
This comment has been minimized.
|
Tracking issue: rust-lang/rust#26391 |
nikomatsakis
merged commit 5646632
into
rust-lang:master
Jun 18, 2015
This comment has been minimized.
This comment has been minimized.
This argument is no longer valid. |
arielb1 commentedApr 10, 2015
Fixes issue #1046.