Skip to content

Commit

Permalink
Deduplicate CoerceUnsized and DispatchFromDyn impl errors
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Feb 24, 2025
1 parent 5c5ed92 commit b46acc0
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 49 deletions.
16 changes: 13 additions & 3 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
Expand Down
3 changes: 0 additions & 3 deletions tests/ui/deriving/deriving-coerce-pointee-neg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,13 @@ 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>)>,
}

#[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>,
Expand All @@ -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() {}
49 changes: 6 additions & 43 deletions tests/ui/deriving/deriving-coerce-pointee-neg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
Expand All @@ -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>,
| ^^^^^^^^^^^^^^
Expand All @@ -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
Expand All @@ -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`.

0 comments on commit b46acc0

Please sign in to comment.