Skip to content

Commit a9a130f

Browse files
committed
Rollup merge of rust-lang#33415 - dfockler:master, r=steveklabnik
Add error explanations for E0374, E0375, E0376 on issue rust-lang#32777
2 parents 03ec483 + 1e901de commit a9a130f

File tree

1 file changed

+158
-7
lines changed

1 file changed

+158
-7
lines changed

Diff for: src/librustc_typeck/diagnostics.rs

+158-7
Original file line numberDiff line numberDiff line change
@@ -3284,6 +3284,164 @@ impl Baz for Bar { } // Note: This is OK
32843284
```
32853285
"##,
32863286

3287+
E0374: r##"
3288+
A struct without a field containing an unsized type cannot implement
3289+
`CoerceUnsized`. An
3290+
[unsized type](https://doc.rust-lang.org/book/unsized-types.html)
3291+
is any type that the compiler doesn't know the length or alignment of at
3292+
compile time. Any struct containing an unsized type is also unsized.
3293+
3294+
Example of erroneous code:
3295+
3296+
```compile_fail
3297+
#![feature(coerce_unsized)]
3298+
use std::ops::CoerceUnsized;
3299+
3300+
struct Foo<T: ?Sized> {
3301+
a: i32,
3302+
}
3303+
3304+
// error: Struct `Foo` has no unsized fields that need `CoerceUnsized`.
3305+
impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
3306+
where T: CoerceUnsized<U> {}
3307+
```
3308+
3309+
`CoerceUnsized` is used to coerce one struct containing an unsized type
3310+
into another struct containing a different unsized type. If the struct
3311+
doesn't have any fields of unsized types then you don't need explicit
3312+
coercion to get the types you want. To fix this you can either
3313+
not try to implement `CoerceUnsized` or you can add a field that is
3314+
unsized to the struct.
3315+
3316+
Example:
3317+
3318+
```
3319+
#![feature(coerce_unsized)]
3320+
use std::ops::CoerceUnsized;
3321+
3322+
// We don't need to impl `CoerceUnsized` here.
3323+
struct Foo {
3324+
a: i32,
3325+
}
3326+
3327+
// We add the unsized type field to the struct.
3328+
struct Bar<T: ?Sized> {
3329+
a: i32,
3330+
b: T,
3331+
}
3332+
3333+
// The struct has an unsized field so we can implement
3334+
// `CoerceUnsized` for it.
3335+
impl<T, U> CoerceUnsized<Bar<U>> for Bar<T>
3336+
where T: CoerceUnsized<U> {}
3337+
```
3338+
3339+
Note that `CoerceUnsized` is mainly used by smart pointers like `Box`, `Rc`
3340+
and `Arc` to be able to mark that they can coerce unsized types that they
3341+
are pointing at.
3342+
"##,
3343+
3344+
E0375: r##"
3345+
A struct with more than one field containing an unsized type cannot implement
3346+
`CoerceUnsized`. This only occurs when you are trying to coerce one of the
3347+
types in your struct to another type in the struct. In this case we try to
3348+
impl `CoerceUnsized` from `T` to `U` which are both types that the struct
3349+
takes. An [unsized type](https://doc.rust-lang.org/book/unsized-types.html)
3350+
is any type that the compiler doesn't know the length or alignment of at
3351+
compile time. Any struct containing an unsized type is also unsized.
3352+
3353+
Example of erroneous code:
3354+
3355+
```compile_fail
3356+
#![feature(coerce_unsized)]
3357+
use std::ops::CoerceUnsized;
3358+
3359+
struct Foo<T: ?Sized, U: ?Sized> {
3360+
a: i32,
3361+
b: T,
3362+
c: U,
3363+
}
3364+
3365+
// error: Struct `Foo` has more than one unsized field.
3366+
impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
3367+
```
3368+
3369+
`CoerceUnsized` only allows for coercion from a structure with a single
3370+
unsized type field to another struct with a single unsized type field.
3371+
In fact Rust only allows for a struct to have one unsized type in a struct
3372+
and that unsized type must be the last field in the struct. So having two
3373+
unsized types in a single struct is not allowed by the compiler. To fix this
3374+
use only one field containing an unsized type in the struct and then use
3375+
multiple structs to manage each unsized type field you need.
3376+
3377+
Example:
3378+
3379+
```
3380+
#![feature(coerce_unsized)]
3381+
use std::ops::CoerceUnsized;
3382+
3383+
struct Foo<T: ?Sized> {
3384+
a: i32,
3385+
b: T,
3386+
}
3387+
3388+
impl <T, U> CoerceUnsized<Foo<U>> for Foo<T>
3389+
where T: CoerceUnsized<U> {}
3390+
3391+
fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
3392+
Foo { a: 12i32, b: t } // we use coercion to get the `Foo<U>` type we need
3393+
}
3394+
```
3395+
3396+
"##,
3397+
3398+
E0376: r##"
3399+
The type you are trying to impl `CoerceUnsized` for is not a struct.
3400+
`CoerceUnsized` can only be implemented for a struct. Unsized types are
3401+
already able to be coerced without an implementation of `CoerceUnsized`
3402+
whereas a struct containing an unsized type needs to know the unsized type
3403+
field it's containing is able to be coerced. An
3404+
[unsized type](https://doc.rust-lang.org/book/unsized-types.html)
3405+
is any type that the compiler doesn't know the length or alignment of at
3406+
compile time. Any struct containing an unsized type is also unsized.
3407+
3408+
Example of erroneous code:
3409+
3410+
```compile_fail
3411+
#![feature(coerce_unsized)]
3412+
use std::ops::CoerceUnsized;
3413+
3414+
struct Foo<T: ?Sized> {
3415+
a: T,
3416+
}
3417+
3418+
// error: The type `U` is not a struct
3419+
impl<T, U> CoerceUnsized<U> for Foo<T> {}
3420+
```
3421+
3422+
The `CoerceUnsized` trait takes a struct type. Make sure the type you are
3423+
providing to `CoerceUnsized` is a struct with only the last field containing an
3424+
unsized type.
3425+
3426+
Example:
3427+
3428+
```
3429+
#![feature(coerce_unsized)]
3430+
use std::ops::CoerceUnsized;
3431+
3432+
struct Foo<T> {
3433+
a: T,
3434+
}
3435+
3436+
// The `Foo<U>` is a struct so `CoerceUnsized` can be implemented
3437+
impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
3438+
```
3439+
3440+
Note that in Rust, structs can only contain an unsized type if the field
3441+
containing the unsized type is the last and only unsized type field in the
3442+
struct.
3443+
"##,
3444+
32873445
E0379: r##"
32883446
Trait methods cannot be declared `const` by design. For more information, see
32893447
[RFC 911].
@@ -3777,13 +3935,6 @@ register_diagnostics! {
37773935
E0320, // recursive overflow during dropck
37783936
E0328, // cannot implement Unsize explicitly
37793937
// E0372, // coherence not object safe
3780-
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
3781-
// between structures with one field being coerced, none found
3782-
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
3783-
// between structures with one field being coerced, but multiple
3784-
// fields need coercions
3785-
E0376, // the trait `CoerceUnsized` may only be implemented for a coercion
3786-
// between structures
37873938
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
37883939
// between structures with the same definition
37893940
E0399, // trait items need to be implemented because the associated

0 commit comments

Comments
 (0)