about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs16
-rw-r--r--tests/ui/deriving/deriving-coerce-pointee-neg.rs3
-rw-r--r--tests/ui/deriving/deriving-coerce-pointee-neg.stderr49
3 files changed, 19 insertions, 49 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 9d6bb1cf6bf..cee2f487639 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -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);
diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.rs b/tests/ui/deriving/deriving-coerce-pointee-neg.rs
index e660e7baacb..2713366945e 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-neg.rs
+++ b/tests/ui/deriving/deriving-coerce-pointee-neg.rs
@@ -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() {}
diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
index e346d13ff5c..d3d73132078 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
+++ b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
@@ -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`.