Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Add some casts I missed the first time around and a few misc. correct…
…ions.
  • Loading branch information
Nick Cameron committed Oct 23, 2014
commit d65c19d26e39d29b80cae0da2d6c5bf28ea79737
26 changes: 19 additions & 7 deletions 0000-coercions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Summary

Describe the various kinds of type conversions available in Rust and suggest
some tweeks.
some tweaks.

Provide a mechanism for smart pointers to be part of the DST coercion system.

Expand Down Expand Up @@ -177,7 +177,7 @@ And where coerce_inner is defined as

* coerce_inner(`(..., T)`) = `(..., coerce_inner(T))`.

Note that coercing from sub-trait to a super-trait it a new coercion and is non-
Note that coercing from sub-trait to a super-trait is a new coercion and is non-
trivial. One implementation strategy which avoids re-computation of vtables is
given in RFC PR #250.

Expand Down Expand Up @@ -259,6 +259,8 @@ Here is an example implementation of `CoerceUnsized` for `Rc`:

```
impl<Sized? T, Sized? U> CoerceUnsized<Rc<T>> for Rc<U> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need some kind of where clause for U: CoerceUnsized<T>?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think so. U is just the pointed-to data, it does not need to be coercible. The RcBox is unsized using the fat_pointer_convert intrinsic and automatically has the required Unsize bound.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does that work? As written, it seems like you could [manually] call coerce() to convert any Rc<T> to any other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, actually I guess you do need a where clause on the impl - where U: Unsize<T>. Given that where clause the compiler can derive that RcBox<U>: Unsize<RcBox<T>> an thus that we can call fat_pointer_convert.

where U: Unsize<T>

fn coerce(self) -> Rc<T> {
let new_ptr: *const RcBox<T> = fat_pointer_convert(self._ptr);
Rc { _ptr: new_ptr }
Expand Down Expand Up @@ -304,7 +306,7 @@ reference apply. (Note that the implementation of the coercion isn't so simple,
it is embedded in the search for candidate methods, but from the point of view
of type conversions, that is not relevant).

Alternatively, a recevier coercion may be thought of as a two stage process.
Alternatively, a receiver coercion may be thought of as a two stage process.
First, we dereference and then take the address until the source type has the
same shape (i.e., has the same kind and number of indirection) as the target
type. Then we try to coerce the adjusted source type to the target type using
Expand All @@ -317,13 +319,20 @@ descriptions are equivalent.
Casting is indicated by the `as` keyword. A cast `e as U` is valid if one of the
following holds:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see it spelled out here (but I guess neither are numeric casts), *T -> *U is gonna remain a cast, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No casting from u8 to u32 or u32 to u8?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numeric casts are an omission, I'll add them in.

@ben0x539 what are T and U here? Do you mean an arbitrary cast from one raw pointer type to another?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, *T -> *U for any T and U with any combination of mutability seems to be accepted right now but I'm not seeing it listed here. Would be sad to see it go away!


* `e` has type `T` and `T` coerces to `U`
* `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`, or a raw pointer;
* `e` is a C-like enum and `U` is any integer type, `bool`;

* `T == u8` and `U == char`;
* `e` has type `T` and `T == u8` and `U == char`;

* `T == &[V]` or `T == &[V, ..n]` and `U == *V`.
* `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`.

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
Expand Down Expand Up @@ -420,6 +429,9 @@ worse.

These rules could be tweaked in any number of ways.

Specifically for the DST custom coercions, the compiler could throw an error if
it finds a user-supplied implementation of the `Unsize` trait, rather than
silently ignoring them.

# Unresolved questions