1
Fork 0

Consolidate and rework CoercePointee and DispatchFromDyn errors

This commit is contained in:
Michael Goulet 2025-02-19 19:10:01 +00:00
parent b6899ab921
commit 96d966b07a
19 changed files with 163 additions and 281 deletions

View file

@ -1,5 +1,5 @@
`CoerceUnsized` was implemented on a struct which does not contain a field with `CoerceUnsized` or `DispatchFromDyn` was implemented on a struct which does not
an unsized type. contain a field that is being unsized.
Example of erroneous code: Example of erroneous code:
@ -11,47 +11,20 @@ struct Foo<T: ?Sized> {
a: i32, 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> impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
where T: CoerceUnsized<U> {} where T: CoerceUnsized<U> {}
``` ```
An [unsized type][1] is any type where the compiler does not know the length or `CoerceUnsized` is used to coerce structs that have a field that can be unsized,
alignment of at compile time. Any struct containing an unsized type is also like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
unsized. 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 Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
into another struct containing a different unsized type. If the struct like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
doesn't have any fields of unsized types then you don't need explicit that they are pointing at.
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.

View file

@ -1,5 +1,5 @@
`CoerceUnsized` was implemented on a struct which contains more than one field `CoerceUnsized` or `DispatchFromDyn` was implemented on a struct which contains
with an unsized type. more than one field that is being unsized.
Erroneous code example: Erroneous code example:
@ -17,39 +17,14 @@ struct Foo<T: ?Sized, U: ?Sized> {
impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} 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` is used to coerce structs that have a field that can be unsized,
`CoerceUnsized`. This only occurs when you are trying to coerce one of the like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
types in your struct to another type in the struct. In this case we try to is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
impl `CoerceUnsized` from `T` to `U` which are both types that the struct trait.
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` only allows for coercion from a structure with a single If the struct has multiple fields that must be unsized, then the compiler has no
unsized type field to another struct with a single unsized type field. way to generate a valid implementation of `CoerceUnsized` or `DispatchFromDyn`.
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.
Example: 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.
#![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

View file

@ -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: Erroneous code example:
```compile_fail,E0376 ```compile_fail,E0377
#![feature(coerce_unsized)] #![feature(coerce_unsized)]
use std::ops::CoerceUnsized; use std::ops::CoerceUnsized;
@ -14,33 +17,4 @@ struct Foo<T: ?Sized> {
impl<T, U> CoerceUnsized<U> for Foo<T> {} impl<T, U> CoerceUnsized<U> for Foo<T> {}
``` ```
`CoerceUnsized` can only be implemented for a struct. Unsized types are `CoerceUnsized` or `DispatchFromDyn` can only be implemented between structs.
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.

View file

@ -1,5 +1,5 @@
The trait `CoerceUnsized` may only be implemented for a coercion between `CoerceUnsized` or `DispatchFromDyn` may only be implemented between structs
structures with the same definition. of the same type.
Example of erroneous code: 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> {} impl<T, U> CoerceUnsized<Bar<U>> for Foo<T> where T: CoerceUnsized<U> {}
``` ```
When attempting to implement `CoerceUnsized`, the `impl` signature must look `CoerceUnsized` is used to coerce structs that have a field that can be unsized,
like: `impl CoerceUnsized<Type<U>> for Type<T> where T: CoerceUnsized<U>`; like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
the *implementer* and *`CoerceUnsized` type parameter* must be the same is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
type. In this example, `Bar` and `Foo` (even though structurally identical) trait.
are *not* the same type and are rejected. Learn more about the `CoerceUnsized`
trait and DST coercion in The compiler cannot support coercions between structs of different types, so
[the `CoerceUnsized` docs](../std/ops/trait.CoerceUnsized.html). 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.

View file

@ -85,6 +85,10 @@ hir_analysis_cmse_output_stack_spill =
.note1 = functions with the `{$abi}` ABI must pass their result via the available return registers .note1 = functions with the `{$abi}` ABI must pass their result via the available return registers
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
hir_analysis_coerce_multi = implementing `{$trait_name}` does not allow multiple fields to be coerced
.note = the trait `{$trait_name}` may only be implemented when a single field is being coerced
.label = these fields must be coerced for `{$trait_name}` to be valid
hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field
hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden
@ -97,10 +101,7 @@ hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only ap
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions hir_analysis_coerce_zero = implementing `{$trait_name}` requires a field to be coerced
.note = `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
.coercions_note = currently, {$number} fields need coercions: {$coercions}
.label = requires multiple coercions
hir_analysis_coercion_between_struct_same_note = expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}` hir_analysis_coercion_between_struct_same_note = expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}`
@ -139,10 +140,6 @@ hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `
hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate
.label = can't implement cross-crate trait for type in another crate .label = can't implement cross-crate trait for type in another crate
hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
.note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
.coercions_note = currently, {$number} fields need coercions: {$coercions}
hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else

View file

@ -240,16 +240,17 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
(&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()), (&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
(&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => { (&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => {
if def_a != def_b { if def_a != def_b {
let source_path = tcx.def_path_str(def_a.did()); if def_a != def_b {
let target_path = tcx.def_path_str(def_b.did()); let source_path = tcx.def_path_str(def_a.did());
let target_path = tcx.def_path_str(def_b.did());
return Err(tcx.dcx().emit_err(errors::DispatchFromDynCoercion { return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
span, span,
trait_name: "DispatchFromDyn", trait_name: "DispatchFromDyn",
note: true, note: true,
source_path, source_path,
target_path, target_path,
})); }));
}
} }
if def_a.repr().c() || def_a.repr().packed() { if def_a.repr().c() || def_a.repr().packed() {
@ -301,43 +302,33 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
None None
} else { } else {
Some((i, ty_a, ty_b)) Some((i, ty_a, ty_b, tcx.def_span(field.did)))
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
res?; res?;
if coerced_fields.is_empty() { if coerced_fields.is_empty() {
return Err(tcx.dcx().emit_err(errors::DispatchFromDynSingle { return Err(tcx.dcx().emit_err(errors::CoerceNoField {
span, span,
trait_name: "DispatchFromDyn", trait_name: "DispatchFromDyn",
note: true, note: true,
})); }));
} else if coerced_fields.len() > 1 { } else if coerced_fields.len() > 1 {
return Err(tcx.dcx().emit_err(errors::DispatchFromDynMulti { return Err(tcx.dcx().emit_err(errors::CoerceMulti {
span, span,
coercions_note: true, trait_name: "DispatchFromDyn",
number: coerced_fields.len(), number: coerced_fields.len(),
coercions: coerced_fields fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
.iter()
.map(|&(i, ty_a, ty_b)| {
format!("`{}` (`{}` to `{}`)", fields[i].name, ty_a, ty_b,)
})
.collect::<Vec<_>>()
.join(", "),
})); }));
} else { } else {
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
for (_, ty_a, ty_b) in coerced_fields { for (_, ty_a, ty_b, _) in coerced_fields {
ocx.register_obligation(Obligation::new( ocx.register_obligation(Obligation::new(
tcx, tcx,
cause.clone(), cause.clone(),
param_env, param_env,
ty::TraitRef::new( ty::TraitRef::new(tcx, dispatch_from_dyn_trait, [ty_a, ty_b]),
tcx,
dispatch_from_dyn_trait,
[ty_a, ty_b],
),
)); ));
} }
let errors = ocx.select_all_or_error(); let errors = ocx.select_all_or_error();
@ -353,7 +344,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
} }
_ => Err(tcx _ => Err(tcx
.dcx() .dcx()
.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" })), .emit_err(errors::CoerceUnsizedNonStruct { span, trait_name: "DispatchFromDyn" })),
} }
} }
@ -419,7 +410,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
if def_a != def_b { if def_a != def_b {
let source_path = tcx.def_path_str(def_a.did()); let source_path = tcx.def_path_str(def_a.did());
let target_path = tcx.def_path_str(def_b.did()); let target_path = tcx.def_path_str(def_b.did());
return Err(tcx.dcx().emit_err(errors::DispatchFromDynSame { return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
span, span,
trait_name: "CoerceUnsized", trait_name: "CoerceUnsized",
note: true, note: true,
@ -501,12 +492,12 @@ pub(crate) fn coerce_unsized_info<'tcx>(
// Collect up all fields that were significantly changed // Collect up all fields that were significantly changed
// i.e., those that contain T in coerce_unsized T -> U // i.e., those that contain T in coerce_unsized T -> U
Some((i, a, b)) Some((i, a, b, tcx.def_span(f.did)))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if diff_fields.is_empty() { if diff_fields.is_empty() {
return Err(tcx.dcx().emit_err(errors::CoerceUnsizedOneField { return Err(tcx.dcx().emit_err(errors::CoerceNoField {
span, span,
trait_name: "CoerceUnsized", trait_name: "CoerceUnsized",
note: true, note: true,
@ -519,19 +510,15 @@ pub(crate) fn coerce_unsized_info<'tcx>(
tcx.def_span(impl_did) tcx.def_span(impl_did)
}; };
return Err(tcx.dcx().emit_err(errors::CoerceUnsizedMulti { return Err(tcx.dcx().emit_err(errors::CoerceMulti {
span, span,
coercions_note: true, trait_name: "CoerceUnsized",
number: diff_fields.len(), number: diff_fields.len(),
coercions: diff_fields fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
.iter()
.map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b))
.collect::<Vec<_>>()
.join(", "),
})); }));
} }
let (i, a, b) = diff_fields[0]; let (i, a, b, _) = diff_fields[0];
let kind = ty::adjustment::CustomCoerceUnsized::Struct(i); let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
(a, b, coerce_unsized_trait, Some(kind)) (a, b, coerce_unsized_trait, Some(kind))
} }
@ -539,7 +526,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
_ => { _ => {
return Err(tcx return Err(tcx
.dcx() .dcx()
.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" })); .emit_err(errors::CoerceUnsizedNonStruct { span, trait_name: "CoerceUnsized" }));
} }
}; };

View file

@ -1164,18 +1164,6 @@ pub(crate) struct InherentTyOutside {
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
pub(crate) struct DispatchFromDynCoercion<'a> {
#[primary_span]
pub span: Span,
pub trait_name: &'a str,
#[note(hir_analysis_coercion_between_struct_same_note)]
pub note: bool,
pub source_path: String,
pub target_path: String,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] #[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)]
pub(crate) struct DispatchFromDynRepr { pub(crate) struct DispatchFromDynRepr {
@ -1293,78 +1281,46 @@ pub(crate) struct DispatchFromDynZST<'a> {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0378)] #[diag(hir_analysis_coerce_zero, code = E0374)]
pub(crate) struct DispatchFromDynSingle<'a> { pub(crate) struct CoerceNoField {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub trait_name: &'a str, pub trait_name: &'static str,
#[note(hir_analysis_coercion_between_struct_single_note)] #[note(hir_analysis_coercion_between_struct_single_note)]
pub note: bool, pub note: bool,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)] #[diag(hir_analysis_coerce_multi, code = E0375)]
#[note] pub(crate) struct CoerceMulti {
pub(crate) struct DispatchFromDynMulti { pub trait_name: &'static str,
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
#[note(hir_analysis_coercions_note)]
pub coercions_note: bool,
pub number: usize, pub number: usize,
pub coercions: String, #[note]
} pub fields: MultiSpan,
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0376)]
pub(crate) struct DispatchFromDynStruct<'a> {
#[primary_span]
pub span: Span,
pub trait_name: &'a str,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0377)] #[diag(hir_analysis_coerce_unsized_may, code = E0377)]
pub(crate) struct DispatchFromDynSame<'a> { pub(crate) struct CoerceUnsizedNonStruct {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub trait_name: &'a str, pub trait_name: &'static str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
pub(crate) struct CoerceSameStruct {
#[primary_span]
pub span: Span,
pub trait_name: &'static str,
#[note(hir_analysis_coercion_between_struct_same_note)] #[note(hir_analysis_coercion_between_struct_same_note)]
pub note: bool, pub note: bool,
pub source_path: String, pub source_path: String,
pub target_path: String, pub target_path: String,
} }
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0374)]
pub(crate) struct CoerceUnsizedOneField<'a> {
#[primary_span]
pub span: Span,
pub trait_name: &'a str,
#[note(hir_analysis_coercion_between_struct_single_note)]
pub note: bool,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_multi, code = E0375)]
#[note]
pub(crate) struct CoerceUnsizedMulti {
#[primary_span]
#[label]
pub span: Span,
#[note(hir_analysis_coercions_note)]
pub coercions_note: bool,
pub number: usize,
pub coercions: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
pub(crate) struct CoerceUnsizedMay<'a> {
#[primary_span]
pub span: Span,
pub trait_name: &'a str,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)] #[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)]
pub(crate) struct TraitCannotImplForTy { pub(crate) struct TraitCannotImplForTy {

View file

@ -1,11 +1,16 @@
error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
--> $DIR/issue-26905.rs:16:40 --> $DIR/issue-26905.rs:16:40
| |
LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ } LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
| ^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions | ^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
= note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData<T>` to `NotPhantomData<U>`) --> $DIR/issue-26905.rs:12:5
|
LL | _ptr: *const T,
| ^^^^^^^^^^^^^^
LL | _boo: NotPhantomData<T>,
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -6,7 +6,7 @@ LL | struct Foo<T: ?Sized> {
| |
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures error[E0374]: implementing `CoerceUnsized` requires a field to be coerced
--> $DIR/E0374.rs:8:1 --> $DIR/E0374.rs:8:1
| |
LL | / impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> LL | / impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>

View file

@ -23,14 +23,19 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | b: Box<T>, LL | b: Box<T>,
| ++++ + | ++++ +
error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
--> $DIR/E0375.rs:10:12 --> $DIR/E0375.rs:10:12
| |
LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions | ^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
= note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) --> $DIR/E0375.rs:6:5
|
LL | b: T,
| ^^^^
LL | c: U,
| ^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -1,10 +0,0 @@
#![feature(coerce_unsized)]
use std::ops::CoerceUnsized;
struct Foo<T: ?Sized> {
a: T,
}
impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
fn main() {}

View file

@ -1,9 +0,0 @@
error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
--> $DIR/E0376.rs:8:1
|
LL | impl<T, U> CoerceUnsized<U> for Foo<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0376`.

View file

@ -8,9 +8,10 @@ use std::{
struct WrapperWithExtraField<T>(T, i32); struct WrapperWithExtraField<T>(T, i32);
impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T> impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
//~^ ERROR [E0378]
where where
T: DispatchFromDyn<U>, T: DispatchFromDyn<U>,
{} //~^^^ ERROR [E0378] {}
struct MultiplePointers<T: ?Sized>{ struct MultiplePointers<T: ?Sized>{
@ -19,9 +20,10 @@ struct MultiplePointers<T: ?Sized>{
} }
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T> impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
//~^ implementing `DispatchFromDyn` does not allow multiple fields to be coerced
where where
T: Unsize<U>, T: Unsize<U>,
{} //~^^^ ERROR [E0378] {}
struct NothingToCoerce<T: ?Sized> { struct NothingToCoerce<T: ?Sized> {
@ -29,23 +31,25 @@ struct NothingToCoerce<T: ?Sized> {
} }
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {} impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
//~^ ERROR [E0378] //~^ ERROR implementing `DispatchFromDyn` requires a field to be coerced
#[repr(C)] #[repr(C)]
struct HasReprC<T: ?Sized>(Box<T>); struct HasReprC<T: ?Sized>(Box<T>);
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T> impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
//~^ ERROR [E0378]
where where
T: Unsize<U>, T: Unsize<U>,
{} //~^^^ ERROR [E0378] {}
#[repr(align(64))] #[repr(align(64))]
struct OverAlignedZst; struct OverAlignedZst;
struct OverAligned<T: ?Sized>(Box<T>, OverAlignedZst); struct OverAligned<T: ?Sized>(Box<T>, OverAlignedZst);
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T> impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
//~^ ERROR [E0378]
where where
T: Unsize<U>, T: Unsize<U>,
{} //~^^^ ERROR [E0378] {}
fn main() {} fn main() {}

View file

@ -2,25 +2,32 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs co
--> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1
| |
LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T> LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
LL | |
LL | | where LL | | where
LL | | T: DispatchFromDyn<U>, LL | | T: DispatchFromDyn<U>,
| |__________________________^ | |__________________________^
| |
= note: extra field `1` of type `i32` is not allowed = note: extra field `1` of type `i32` is not allowed
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
--> $DIR/invalid_dispatch_from_dyn_impls.rs:21:1 --> $DIR/invalid_dispatch_from_dyn_impls.rs:22:1
| |
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T> LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
LL | |
LL | | where LL | | where
LL | | T: Unsize<U>, LL | | T: Unsize<U>,
| |_________________^ | |_________________^
| |
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
= note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`) --> $DIR/invalid_dispatch_from_dyn_impls.rs:18:5
|
LL | ptr1: *const T,
| ^^^^^^^^^^^^^^
LL | ptr2: *const T,
| ^^^^^^^^^^^^^^
error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures error[E0374]: implementing `DispatchFromDyn` requires a field to be coerced
--> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1 --> $DIR/invalid_dispatch_from_dyn_impls.rs:33:1
| |
LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {} LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -28,17 +35,19 @@ LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingT
= note: expected a single field to be coerced, none found = note: expected a single field to be coerced, none found
error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
--> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1 --> $DIR/invalid_dispatch_from_dyn_impls.rs:39:1
| |
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T> LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
LL | |
LL | | where LL | | where
LL | | T: Unsize<U>, LL | | T: Unsize<U>,
| |_________________^ | |_________________^
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else
--> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 --> $DIR/invalid_dispatch_from_dyn_impls.rs:49:1
| |
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T> LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
LL | |
LL | | where LL | | where
LL | | T: Unsize<U>, LL | | T: Unsize<U>,
| |_____________________^ | |_____________________^
@ -47,4 +56,5 @@ LL | | T: Unsize<U>,
error: aborting due to 5 previous errors error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0378`. Some errors have detailed explanations: E0374, E0375, E0378.
For more information about an error, try `rustc --explain E0374`.

View file

@ -15,7 +15,7 @@ struct Dispatchable<T: ?Sized, Z> {
} }
impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()> impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()>
//~^ ERROR implementing the `DispatchFromDyn` trait requires multiple coercions //~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced
where where
T: Unsize<U> + ?Sized, T: Unsize<U> + ?Sized,
U: ?Sized, U: ?Sized,

View file

@ -1,4 +1,4 @@
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
--> $DIR/dispatch-from-dyn-zst-transmute-zst-nonzst.rs:17:1 --> $DIR/dispatch-from-dyn-zst-transmute-zst-nonzst.rs:17:1
| |
LL | / impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()> LL | / impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()>
@ -8,9 +8,14 @@ LL | | T: Unsize<U> + ?Sized,
LL | | U: ?Sized, LL | | U: ?Sized,
| |______________^ | |______________^
| |
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
= note: currently, 2 fields need coercions: `_ptr` (`Box<T>` to `Box<U>`), `z` (`()` to `i32`) --> $DIR/dispatch-from-dyn-zst-transmute-zst-nonzst.rs:13:5
|
LL | _ptr: Box<T>,
| ^^^^^^^^^^^^
LL | z: Z,
| ^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0378`. For more information about this error, try `rustc --explain E0375`.

View file

@ -15,7 +15,7 @@ struct Foo<'a, U: ?Sized> {
} }
impl<'a, T, U> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> impl<'a, T, U> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T>
//~^ ERROR implementing the `DispatchFromDyn` trait requires multiple coercions //~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced
where where
T: Unsize<U> + ?Sized, T: Unsize<U> + ?Sized,
U: ?Sized {} U: ?Sized {}

View file

@ -1,4 +1,4 @@
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
--> $DIR/dispatch-from-dyn-zst-transmute.rs:17:1 --> $DIR/dispatch-from-dyn-zst-transmute.rs:17:1
| |
LL | / impl<'a, T, U> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> LL | / impl<'a, T, U> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T>
@ -8,9 +8,14 @@ LL | | T: Unsize<U> + ?Sized,
LL | | U: ?Sized {} LL | | U: ?Sized {}
| |_____________^ | |_____________^
| |
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
= note: currently, 2 fields need coercions: `token` (`IsSendToken<T>` to `IsSendToken<U>`), `ptr` (`&'a T` to `&'a U`) --> $DIR/dispatch-from-dyn-zst-transmute.rs:13:5
|
LL | token: IsSendToken<U>,
| ^^^^^^^^^^^^^^^^^^^^^
LL | ptr: &'a U,
| ^^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0378`. For more information about this error, try `rustc --explain E0375`.

View file

@ -65,7 +65,7 @@ LL | fn foo(self: Smaht<Self, T>);
= note: type of `self` must be `Self` or a type that dereferences to it = note: type of `self` must be `Self` or a type that dereferences to it
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures error[E0377]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
--> $DIR/issue-78372.rs:3:1 --> $DIR/issue-78372.rs:3:1
| |
LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
@ -73,5 +73,5 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
error: aborting due to 7 previous errors error: aborting due to 7 previous errors
Some errors have detailed explanations: E0307, E0378, E0412, E0658. Some errors have detailed explanations: E0307, E0377, E0412, E0658.
For more information about an error, try `rustc --explain E0307`. For more information about an error, try `rustc --explain E0307`.