Deduplicate CoerceUnsized and DispatchFromDyn impl errors

This commit is contained in:
Michael Goulet 2025-02-19 19:55:12 +00:00
parent 5c5ed92c37
commit b46acc0191
3 changed files with 19 additions and 49 deletions

View file

@ -195,8 +195,7 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E
// Just compute this for the side-effects, in particular reporting
// errors; other parts of the code may demand it for the info of
// course.
let span = tcx.def_span(impl_did);
tcx.at(span).ensure_ok().coerce_unsized_info(impl_did)
tcx.ensure_ok().coerce_unsized_info(impl_did)
}
fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
@ -218,13 +217,24 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
let source = trait_ref.self_ty();
assert!(!source.has_escaping_bound_vars());
let target = {
assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
trait_ref.args.type_at(1)
};
// Check `CoercePointee` impl is WF -- if not, then there's no reason to report
// redundant errors for `DispatchFromDyn`. This is best effort, though.
let mut res = Ok(());
tcx.for_each_relevant_impl(
tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
source,
|impl_def_id| {
res = res.and(tcx.ensure_ok().coerce_unsized_info(impl_def_id));
},
);
res?;
debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
let param_env = tcx.param_env(impl_did);

View file

@ -145,7 +145,6 @@ struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
#[repr(transparent)]
#[derive(CoercePointee)]
//~^ ERROR for `RcWithId<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
//~| ERROR for `RcWithId<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
struct RcWithId<T: ?Sized> {
inner: std::rc::Rc<(i32, Box<T>)>,
}
@ -153,7 +152,6 @@ struct RcWithId<T: ?Sized> {
#[repr(transparent)]
#[derive(CoercePointee)]
//~^ ERROR implementing `CoerceUnsized` does not allow multiple fields to be coerced
//~| ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced
struct MoreThanOneField<T: ?Sized> {
//~^ ERROR transparent struct needs at most one field with non-trivial size or alignment, but has 2
inner1: Box<T>,
@ -165,7 +163,6 @@ struct NotCoercePointeeData<T: ?Sized>(T);
#[repr(transparent)]
#[derive(CoercePointee)]
//~^ ERROR for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
//~| ERROR for `UsingNonCoercePointeeData<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
fn main() {}

View file

@ -118,43 +118,6 @@ error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(
LL | struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: for `RcWithId<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
--> $DIR/deriving-coerce-pointee-neg.rs:146:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
...
LL | inner: std::rc::Rc<(i32, Box<T>)>,
| --------------------------------- `Rc<(i32, Box<T>)>` must be a pointer, reference, or smart pointer that is allowed to be unsized
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
--> $DIR/deriving-coerce-pointee-neg.rs:154:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
--> $DIR/deriving-coerce-pointee-neg.rs:159:5
|
LL | inner1: Box<T>,
| ^^^^^^^^^^^^^^
LL | inner2: Box<T>,
| ^^^^^^^^^^^^^^
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: for `UsingNonCoercePointeeData<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
--> $DIR/deriving-coerce-pointee-neg.rs:166:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
...
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
| ----------------------- `NotCoercePointeeData<T>` must be a pointer, reference, or smart pointer that is allowed to be unsized
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: for `RcWithId<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
--> $DIR/deriving-coerce-pointee-neg.rs:146:10
|
@ -167,13 +130,13 @@ LL | inner: std::rc::Rc<(i32, Box<T>)>,
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
--> $DIR/deriving-coerce-pointee-neg.rs:154:10
--> $DIR/deriving-coerce-pointee-neg.rs:153:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
--> $DIR/deriving-coerce-pointee-neg.rs:159:5
--> $DIR/deriving-coerce-pointee-neg.rs:157:5
|
LL | inner1: Box<T>,
| ^^^^^^^^^^^^^^
@ -182,18 +145,18 @@ LL | inner2: Box<T>,
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
--> $DIR/deriving-coerce-pointee-neg.rs:166:10
--> $DIR/deriving-coerce-pointee-neg.rs:164:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
...
LL |
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
| ----------------------- `NotCoercePointeeData<T>` must be a pointer, reference, or smart pointer that is allowed to be unsized
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0690]: transparent struct needs at most one field with non-trivial size or alignment, but has 2
--> $DIR/deriving-coerce-pointee-neg.rs:157:1
--> $DIR/deriving-coerce-pointee-neg.rs:155:1
|
LL | struct MoreThanOneField<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs at most one field with non-trivial size or alignment, but has 2
@ -203,7 +166,7 @@ LL | inner1: Box<T>,
LL | inner2: Box<T>,
| -------------- this field has non-zero size or requires alignment
error: aborting due to 24 previous errors
error: aborting due to 21 previous errors
Some errors have detailed explanations: E0375, E0392, E0690, E0802.
For more information about an error, try `rustc --explain E0375`.