Consolidate and rework CoercePointee and DispatchFromDyn errors
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
`CoerceUnsized` was implemented on a struct which does not contain a field with
|
||||
an unsized type.
|
||||
`CoerceUnsized` or `DispatchFromDyn` was implemented on a struct which does not
|
||||
contain a field that is being unsized.
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
@@ -11,47 +11,20 @@ struct Foo<T: ?Sized> {
|
||||
a: i32,
|
||||
}
|
||||
|
||||
// error: Struct `Foo` has no unsized fields that need `CoerceUnsized`.
|
||||
// error: Struct `Foo` has no unsized fields that need to be coerced.
|
||||
impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
|
||||
where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
An [unsized type][1] is any type where the compiler does not know the length or
|
||||
alignment of at compile time. Any struct containing an unsized type is also
|
||||
unsized.
|
||||
`CoerceUnsized` is used to coerce structs that have a field that can be unsized,
|
||||
like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
|
||||
is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
|
||||
trait.
|
||||
|
||||
[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
|
||||
If the struct doesn't have any fields of unsized types then there is no
|
||||
meaningful way to implement `CoerceUnsized` or `DispatchFromDyn`, since
|
||||
there is no coercion taking place.
|
||||
|
||||
`CoerceUnsized` is used to coerce one struct containing an unsized type
|
||||
into another struct containing a different unsized type. If the struct
|
||||
doesn't have any fields of unsized types then you don't need explicit
|
||||
coercion to get the types you want. To fix this you can either
|
||||
not try to implement `CoerceUnsized` or you can add a field that is
|
||||
unsized to the struct.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
// We don't need to impl `CoerceUnsized` here.
|
||||
struct Foo {
|
||||
a: i32,
|
||||
}
|
||||
|
||||
// We add the unsized type field to the struct.
|
||||
struct Bar<T: ?Sized> {
|
||||
a: i32,
|
||||
b: T,
|
||||
}
|
||||
|
||||
// The struct has an unsized field so we can implement
|
||||
// `CoerceUnsized` for it.
|
||||
impl<T, U> CoerceUnsized<Bar<U>> for Bar<T>
|
||||
where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
Note that `CoerceUnsized` is mainly used by smart pointers like `Box`, `Rc`
|
||||
and `Arc` to be able to mark that they can coerce unsized types that they
|
||||
are pointing at.
|
||||
Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
|
||||
like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
|
||||
that they are pointing at.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
`CoerceUnsized` was implemented on a struct which contains more than one field
|
||||
with an unsized type.
|
||||
`CoerceUnsized` or `DispatchFromDyn` was implemented on a struct which contains
|
||||
more than one field that is being unsized.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
@@ -17,39 +17,14 @@ struct Foo<T: ?Sized, U: ?Sized> {
|
||||
impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
|
||||
```
|
||||
|
||||
A struct with more than one field containing an unsized type cannot implement
|
||||
`CoerceUnsized`. This only occurs when you are trying to coerce one of the
|
||||
types in your struct to another type in the struct. In this case we try to
|
||||
impl `CoerceUnsized` from `T` to `U` which are both types that the struct
|
||||
takes. An [unsized type][1] is any type that the compiler doesn't know the
|
||||
length or alignment of at compile time. Any struct containing an unsized type
|
||||
is also unsized.
|
||||
`CoerceUnsized` is used to coerce structs that have a field that can be unsized,
|
||||
like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
|
||||
is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
|
||||
trait.
|
||||
|
||||
`CoerceUnsized` only allows for coercion from a structure with a single
|
||||
unsized type field to another struct with a single unsized type field.
|
||||
In fact Rust only allows for a struct to have one unsized type in a struct
|
||||
and that unsized type must be the last field in the struct. So having two
|
||||
unsized types in a single struct is not allowed by the compiler. To fix this
|
||||
use only one field containing an unsized type in the struct and then use
|
||||
multiple structs to manage each unsized type field you need.
|
||||
If the struct has multiple fields that must be unsized, then the compiler has no
|
||||
way to generate a valid implementation of `CoerceUnsized` or `DispatchFromDyn`.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
struct Foo<T: ?Sized> {
|
||||
a: i32,
|
||||
b: T,
|
||||
}
|
||||
|
||||
impl <T, U> CoerceUnsized<Foo<U>> for Foo<T>
|
||||
where T: CoerceUnsized<U> {}
|
||||
|
||||
fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
|
||||
Foo { a: 12i32, b: t } // we use coercion to get the `Foo<U>` type we need
|
||||
}
|
||||
```
|
||||
|
||||
[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
|
||||
Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
|
||||
like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
|
||||
that they are pointing at.
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
`CoerceUnsized` was implemented on something that isn't a struct.
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
`CoerceUnsized` or `DispatchFromDyn` was implemented between two types that
|
||||
are not structs.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0376
|
||||
```compile_fail,E0377
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
@@ -14,33 +17,4 @@ struct Foo<T: ?Sized> {
|
||||
impl<T, U> CoerceUnsized<U> for Foo<T> {}
|
||||
```
|
||||
|
||||
`CoerceUnsized` can only be implemented for a struct. Unsized types are
|
||||
already able to be coerced without an implementation of `CoerceUnsized`
|
||||
whereas a struct containing an unsized type needs to know the unsized type
|
||||
field it's containing is able to be coerced. An [unsized type][1]
|
||||
is any type that the compiler doesn't know the length or alignment of at
|
||||
compile time. Any struct containing an unsized type is also unsized.
|
||||
|
||||
[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
|
||||
|
||||
The `CoerceUnsized` trait takes a struct type. Make sure the type you are
|
||||
providing to `CoerceUnsized` is a struct with only the last field containing an
|
||||
unsized type.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
struct Foo<T> {
|
||||
a: T,
|
||||
}
|
||||
|
||||
// The `Foo<U>` is a struct so `CoerceUnsized` can be implemented
|
||||
impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
Note that in Rust, structs can only contain an unsized type if the field
|
||||
containing the unsized type is the last and only unsized type field in the
|
||||
struct.
|
||||
`CoerceUnsized` or `DispatchFromDyn` can only be implemented between structs.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
The trait `CoerceUnsized` may only be implemented for a coercion between
|
||||
structures with the same definition.
|
||||
`CoerceUnsized` or `DispatchFromDyn` may only be implemented between structs
|
||||
of the same type.
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
@@ -20,10 +20,15 @@ pub struct Bar<T: ?Sized> {
|
||||
impl<T, U> CoerceUnsized<Bar<U>> for Foo<T> where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
When attempting to implement `CoerceUnsized`, the `impl` signature must look
|
||||
like: `impl CoerceUnsized<Type<U>> for Type<T> where T: CoerceUnsized<U>`;
|
||||
the *implementer* and *`CoerceUnsized` type parameter* must be the same
|
||||
type. In this example, `Bar` and `Foo` (even though structurally identical)
|
||||
are *not* the same type and are rejected. Learn more about the `CoerceUnsized`
|
||||
trait and DST coercion in
|
||||
[the `CoerceUnsized` docs](../std/ops/trait.CoerceUnsized.html).
|
||||
`CoerceUnsized` is used to coerce structs that have a field that can be unsized,
|
||||
like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
|
||||
is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
|
||||
trait.
|
||||
|
||||
The compiler cannot support coercions between structs of different types, so
|
||||
a valid implementation of `CoerceUnsized` or `DispatchFromDyn` should be
|
||||
implemented between the same struct with different generic parameters.
|
||||
|
||||
Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
|
||||
like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
|
||||
that they are pointing at.
|
||||
|
||||
Reference in New Issue
Block a user