about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOhad Ravid <ohad.rv@gmail.com>2019-11-09 17:32:15 +0100
committerOhad Ravid <ohad.rv@gmail.com>2019-11-10 16:26:38 +0100
commit2db744ca9d4da28c5d0088f5d21e237e7f678abb (patch)
tree56b5ef21496e81efcd8abc464489e96b932f0019
parent7e94cc37e8d4938da29def5f49ae9fec56ca7dec (diff)
downloadrust-2db744ca9d4da28c5d0088f5d21e237e7f678abb.tar.gz
rust-2db744ca9d4da28c5d0088f5d21e237e7f678abb.zip
Improve coherence errors for wrong type order
-rw-r--r--src/librustc/traits/coherence.rs12
-rw-r--r--src/librustc_typeck/coherence/orphan.rs64
-rw-r--r--src/librustc_typeck/error_codes.rs9
-rw-r--r--src/test/ui/coherence/coherence-all-remote.stderr1
-rw-r--r--src/test/ui/coherence/coherence-bigint-param.stderr7
-rw-r--r--src/test/ui/coherence/coherence-cross-crate-conflict.stderr1
-rw-r--r--src/test/ui/coherence/coherence-lone-type-parameter.stderr1
-rw-r--r--src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr1
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr2
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr1
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr2
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr2
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr2
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs4
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr14
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs4
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr14
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs2
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr7
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr1
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr2
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr1
-rw-r--r--src/test/ui/error-codes/e0119/issue-28981.stderr1
-rw-r--r--src/test/ui/issues/issue-41974.stderr1
-rw-r--r--src/test/ui/orphan-check-diagnostics.stderr1
25 files changed, 110 insertions, 47 deletions
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 1645f94535f..778bba1eef6 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -238,7 +238,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(
 
 pub enum OrphanCheckErr<'tcx> {
     NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
-    UncoveredTy(Ty<'tcx>),
+    UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
 }
 
 /// Checks the coherence orphan rules. `impl_def_id` should be the
@@ -402,7 +402,15 @@ fn orphan_check_trait_ref<'tcx>(
             return Ok(());
         } else if let ty::Param(_) = input_ty.kind {
             debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
-            return Err(OrphanCheckErr::UncoveredTy(input_ty))
+            let local_type = trait_ref
+                .input_types()
+                .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
+                .filter(|ty| ty_is_non_local_constructor(tcx, ty, in_crate).is_none())
+                .next();
+
+            debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
+
+            return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type))
         }
         if let Some(non_local_tys) = non_local_tys {
             for input_ty in non_local_tys {
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index f066ca762c0..88fa09cc936 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -77,30 +77,58 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
                     err.emit();
                     return;
                 }
-                Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
+                Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => {
                     let mut sp = sp;
                     for param in &generics.params {
                         if param.name.ident().to_string() == param_ty.to_string() {
                             sp = param.span;
                         }
                     }
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        sp,
-                        E0210,
-                        "type parameter `{}` must be used as the type parameter for some local \
-                         type (e.g., `MyStruct<{}>`)",
-                        param_ty,
-                        param_ty
-                    );
-                    err.span_label(sp, format!(
-                        "type parameter `{}` must be used as the type parameter for some local \
-                         type",
-                        param_ty,
-                    ));
-                    err.note("only traits defined in the current crate can be implemented for a \
-                              type parameter");
-                    err.emit();
+
+                    match local_type {
+                        Some(local_type) => {
+                            struct_span_err!(
+                                self.tcx.sess,
+                                sp,
+                                E0210,
+                                "type parameter `{}` must be covered by another type \
+                                when it appears before the first local type (`{}`)",
+                                param_ty,
+                                local_type
+                            ).span_label(sp, format!(
+                                "type parameter `{}` must be covered by another type \
+                                when it appears before the first local type (`{}`)",
+                                param_ty,
+                                local_type
+                            )).note("implementing a foreign trait is only possible if at \
+                                    least one of the types for which is it implemented is local, \
+                                    and no uncovered type parameters appear before that first \
+                                    local type"
+                            ).note("in this case, 'before' refers to the following order: \
+                                    `impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
+                                    where `T0` is the first and `Tn` is the last"
+                            ).emit();
+                        }
+                        None => {
+                            struct_span_err!(
+                                self.tcx.sess,
+                                sp,
+                                E0210,
+                                "type parameter `{}` must be used as the type parameter for some \
+                                local type (e.g., `MyStruct<{}>`)",
+                                param_ty,
+                                param_ty
+                            ).span_label(sp, format!(
+                                "type parameter `{}` must be used as the type parameter for some \
+                                local type",
+                                param_ty,
+                            )).note("implementing a foreign trait is only possible if at \
+                                    least one of the types for which is it implemented is local"
+                            ).note("only traits defined in the current crate can be \
+                                    implemented for a type parameter"
+                            ).emit();
+                        }
+                    };
                     return;
                 }
             }
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index 9417e78ebfa..6e8ba7089cf 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -2124,10 +2124,11 @@ where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
 are types. One of the types `T0, ..., Tn` must be a local type (this is another
 orphan rule, see the explanation for E0117).
 
-Both of the folowing must be true:
-1. At least one of the types T0..=Tn must be a local type.
-Let Ti be the first such type.
-2. No uncovered type parameters P1..=Pm may appear in T0..Ti (excluding Ti).
+Both of the following must be true:
+1. At least one of the types `T0..=Tn` must be a local type.
+Let `Ti` be the first such type.
+2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti`
+(excluding `Ti`).
 
 For information on the design of the orphan rules,
 see [RFC 2451] and [RFC 1023].
diff --git a/src/test/ui/coherence/coherence-all-remote.stderr b/src/test/ui/coherence/coherence-all-remote.stderr
index b35ae46f888..6ecfb2c5eb0 100644
--- a/src/test/ui/coherence/coherence-all-remote.stderr
+++ b/src/test/ui/coherence/coherence-all-remote.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<T> for isize { }
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-bigint-param.stderr b/src/test/ui/coherence/coherence-bigint-param.stderr
index bb81d7adea2..d431c5f4b52 100644
--- a/src/test/ui/coherence/coherence-bigint-param.stderr
+++ b/src/test/ui/coherence/coherence-bigint-param.stderr
@@ -1,10 +1,11 @@
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
   --> $DIR/coherence-bigint-param.rs:8:6
    |
 LL | impl<T> Remote1<BigInt> for T { }
-   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
    |
-   = note: only traits defined in the current crate can be implemented for a type parameter
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr
index cb66f9b0c7f..c00751a0f23 100644
--- a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr
+++ b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr
@@ -13,6 +13,7 @@ error[E0210]: type parameter `A` must be used as the type parameter for some loc
 LL | impl<A> Foo for A {
    |      ^ type parameter `A` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/coherence-lone-type-parameter.stderr b/src/test/ui/coherence/coherence-lone-type-parameter.stderr
index 3791d96302b..2c3b4fc3ad2 100644
--- a/src/test/ui/coherence/coherence-lone-type-parameter.stderr
+++ b/src/test/ui/coherence/coherence-lone-type-parameter.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote for T { }
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
index 69194bdaf56..8a951d407ca 100644
--- a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
+++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote for Box<T> {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr
index b0f34419bb3..c5759244eff 100644
--- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<u32> for Box<T> {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<'a, T> Remote1<u32> for &'a T {
    |          ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr
index 002f8b7286a..e8663fd7d82 100644
--- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<u32> for T {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr
index 0c43936e6d4..639bee2b8ec 100644
--- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<Box<T>> for u32 {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<'a, T> Remote1<&'a T> for u32 {
    |          ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr
index f81f15b204b..0b6c81b53cd 100644
--- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<'a, T> Remote1<Box<T>> for &'a T {
    |          ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<'a, T> Remote1<&'a T> for Box<T> {
    |          ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr
index 24fd492c57c..fe40490822e 100644
--- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<Box<T>> for T {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<'a, T> Remote1<&'a T> for T {
    |          ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs
index 4666e449ca9..c9e3594cd34 100644
--- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs
@@ -8,11 +8,11 @@ use std::rc::Rc;
 struct Local;
 
 impl<T> Remote2<Box<T>, Local> for u32 {
-    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+    //~^ ERROR type parameter `T` must be covered by another type
 }
 
 impl<'a, T> Remote2<&'a T, Local> for u32 {
-    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+    //~^ ERROR type parameter `T` must be covered by another type
 }
 
 fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr
index 6a1db165416..1eaef59b3f8 100644
--- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr
@@ -1,18 +1,20 @@
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
   --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:10:6
    |
 LL | impl<T> Remote2<Box<T>, Local> for u32 {
-   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
    |
-   = note: only traits defined in the current crate can be implemented for a type parameter
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
   --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:14:10
    |
 LL | impl<'a, T> Remote2<&'a T, Local> for u32 {
-   |          ^ type parameter `T` must be used as the type parameter for some local type
+   |          ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
    |
-   = note: only traits defined in the current crate can be implemented for a type parameter
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs
index db88c330b39..7709bd9c89b 100644
--- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs
@@ -8,11 +8,11 @@ use std::rc::Rc;
 struct Local;
 
 impl<T> Remote1<Local> for Box<T> {
-    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+    //~^ ERROR type parameter `T` must be covered by another type
 }
 
 impl<T> Remote1<Local> for &T {
-    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+    //~^ ERROR type parameter `T` must be covered by another type
 }
 
 fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr
index b5fdb16c2f3..4d39186d494 100644
--- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr
@@ -1,18 +1,20 @@
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
   --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:10:6
    |
 LL | impl<T> Remote1<Local> for Box<T> {
-   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
    |
-   = note: only traits defined in the current crate can be implemented for a type parameter
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
   --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:14:6
    |
 LL | impl<T> Remote1<Local> for &T {
-   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
    |
-   = note: only traits defined in the current crate can be implemented for a type parameter
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs
index dd4110d31e6..eed3a4b5c23 100644
--- a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs
@@ -8,7 +8,7 @@ use std::rc::Rc;
 struct Local;
 
 impl<T> Remote1<Local> for T {
-    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+    //~^ ERROR type parameter `T` must be covered by another type
 }
 
 fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr
index 7b65212f62a..d74be4cec72 100644
--- a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr
@@ -1,10 +1,11 @@
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
   --> $DIR/impl[t]-foreign[local]-for-t.rs:10:6
    |
 LL | impl<T> Remote1<Local> for T {
-   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
    |
-   = note: only traits defined in the current crate can be implemented for a type parameter
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr
index 2e5ae6a8eb3..b26feb4914c 100644
--- a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<T> for u32 {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr
index 3976f06947f..5e8cc552c98 100644
--- a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<T> for Box<T> {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct<B>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `B` must be used as the type parameter for some loc
 LL | impl<'a, A, B> Remote1<A> for &'a B {
    |             ^ type parameter `B` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr
index 8d858b8abee..d3226d33bee 100644
--- a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Remote1<T> for T {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr
index ec8e8144d42..2a78cc8b2db 100644
--- a/src/test/ui/error-codes/e0119/issue-28981.stderr
+++ b/src/test/ui/error-codes/e0119/issue-28981.stderr
@@ -14,6 +14,7 @@ error[E0210]: type parameter `Foo` must be used as the type parameter for some l
 LL | impl<Foo> Deref for Foo { }
    |      ^^^ type parameter `Foo` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr
index 12d4da71599..9f164822dea 100644
--- a/src/test/ui/issues/issue-41974.stderr
+++ b/src/test/ui/issues/issue-41974.stderr
@@ -21,6 +21,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> Drop for T where T: A {
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/orphan-check-diagnostics.stderr b/src/test/ui/orphan-check-diagnostics.stderr
index cb21b26bba7..c84d401898c 100644
--- a/src/test/ui/orphan-check-diagnostics.stderr
+++ b/src/test/ui/orphan-check-diagnostics.stderr
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
 LL | impl<T> RemoteTrait for T where T: LocalTrait {}
    |      ^ type parameter `T` must be used as the type parameter for some local type
    |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
 error: aborting due to previous error