about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-11-11 05:47:37 +0000
committerbors <bors@rust-lang.org>2021-11-11 05:47:37 +0000
commit1d34cb4efccb6ec47c2eb478e4cc900936dfe387 (patch)
treeba618f35f11be61c7d19bc7dcb81f25ea6ce462f
parent9dbbbb12c0b796f35cbf5a518ac12846c969a214 (diff)
parentf55ff4103f4e75309954cfe93ea0994646430fbb (diff)
downloadrust-1d34cb4efccb6ec47c2eb478e4cc900936dfe387.tar.gz
rust-1d34cb4efccb6ec47c2eb478e4cc900936dfe387.zip
Auto merge of #89550 - lcnr:coherence-specialization, r=nikomatsakis
do not emit overlap errors for impls failing the orphan check

this should finally allow us to merge #86986, see https://github.com/rust-lang/rust/pull/86986#discussion_r716059345 for more details.

r? `@nikomatsakis` cc `@eddyb`
-rw-r--r--compiler/rustc_middle/src/query/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs13
-rw-r--r--compiler/rustc_typeck/src/coherence/mod.rs8
-rw-r--r--compiler/rustc_typeck/src/coherence/orphan.rs464
-rw-r--r--src/test/ui/coherence/coherence-cross-crate-conflict.rs4
-rw-r--r--src/test/ui/coherence/coherence-cross-crate-conflict.stderr14
-rw-r--r--src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr24
-rw-r--r--src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr24
-rw-r--r--src/test/ui/coherence/coherence-impls-copy.rs6
-rw-r--r--src/test/ui/coherence/coherence-impls-copy.stderr83
-rw-r--r--src/test/ui/coherence/coherence-impls-send.rs3
-rw-r--r--src/test/ui/coherence/coherence-impls-send.stderr15
-rw-r--r--src/test/ui/coherence/coherence-impls-sized.stderr66
-rw-r--r--src/test/ui/coherence/coherence-orphan.stderr22
-rw-r--r--src/test/ui/dropck/drop-on-non-struct.stderr12
-rw-r--r--src/test/ui/error-codes/E0117.stderr12
-rw-r--r--src/test/ui/error-codes/e0119/complex-impl.rs1
-rw-r--r--src/test/ui/error-codes/e0119/complex-impl.stderr15
-rw-r--r--src/test/ui/error-codes/e0119/issue-28981.rs1
-rw-r--r--src/test/ui/error-codes/e0119/issue-28981.stderr15
-rw-r--r--src/test/ui/issues/issue-41974.rs6
-rw-r--r--src/test/ui/issues/issue-41974.stderr27
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr95
-rw-r--r--src/test/ui/traits/alias/issue-83613.stderr16
-rw-r--r--src/test/ui/traits/issue-78372.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr15
28 files changed, 501 insertions, 497 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a9f94b74c5e..9a58009a173 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -822,6 +822,14 @@ rustc_queries! {
         desc { "check for overlap between inherent impls defined in this crate" }
     }
 
+    /// Checks whether all impls in the crate pass the overlap check, returning
+    /// which impls fail it. If all impls are correct, the returned slice is empty.
+    query orphan_check_crate(_: ()) -> &'tcx [LocalDefId] {
+        desc {
+            "checking whether the immpl in the this crate follow the orphan rules",
+        }
+    }
+
     /// Check whether the function has any recursion that could cause the inliner to trigger
     /// a cycle. Returns the call stack causing the cycle. The call stack does not contain the
     /// current function, just all intermediate functions.
@@ -1056,11 +1064,6 @@ rustc_queries! {
     }
 
     /// Return all `impl` blocks in the current crate.
-    ///
-    /// To allow caching this between crates, you must pass in [`LOCAL_CRATE`] as the crate number.
-    /// Passing in any other crate will cause an ICE.
-    ///
-    /// [`LOCAL_CRATE`]: rustc_hir::def_id::LOCAL_CRATE
     query all_local_trait_impls(_: ()) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> {
         desc { "local trait impls" }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index f81a74a67dc..b64c5559227 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -291,6 +291,11 @@ pub(super) fn specialization_graph_provider(
     sg
 }
 
+// This function is only used when
+// encountering errors and inlining
+// it negatively impacts perf.
+#[cold]
+#[inline(never)]
 fn report_overlap_conflict(
     tcx: TyCtxt<'_>,
     overlap: OverlapError,
@@ -443,8 +448,12 @@ fn report_conflicting_impls(
     match used_to_be_allowed {
         None => {
             sg.has_errored = true;
-            let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
-            decorate(LintDiagnosticBuilder::new(err));
+            if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) {
+                let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
+                decorate(LintDiagnosticBuilder::new(err));
+            } else {
+                tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check");
+            }
         }
         Some(kind) => {
             let lint = match kind {
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs
index 079604f128d..377ebf1fe2a 100644
--- a/compiler/rustc_typeck/src/coherence/mod.rs
+++ b/compiler/rustc_typeck/src/coherence/mod.rs
@@ -168,6 +168,7 @@ pub fn provide(providers: &mut Providers) {
     use self::builtin::coerce_unsized_info;
     use self::inherent_impls::{crate_inherent_impls, inherent_impls};
     use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
+    use self::orphan::orphan_check_crate;
 
     *providers = Providers {
         coherent_trait,
@@ -175,6 +176,7 @@ pub fn provide(providers: &mut Providers) {
         inherent_impls,
         crate_inherent_impls_overlap_check,
         coerce_unsized_info,
+        orphan_check_crate,
         ..*providers
     };
 }
@@ -195,13 +197,13 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
 }
 
 pub fn check_coherence(tcx: TyCtxt<'_>) {
+    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
+    tcx.ensure().orphan_check_crate(());
+
     for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
         tcx.ensure().coherent_trait(trait_def_id);
     }
 
-    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
-    tcx.sess.time("orphan_checking", || orphan::check(tcx));
-
     // these queries are executed for side-effects (error reporting):
     tcx.ensure().crate_inherent_impls(());
     tcx.ensure().crate_inherent_impls_overlap_check(());
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs
index 0326d1fd74f..b450d3f6c08 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_typeck/src/coherence/orphan.rs
@@ -2,250 +2,266 @@
 //! crate or pertains to a type defined in this crate.
 
 use rustc_errors::struct_span_err;
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::Span;
 use rustc_trait_selection::traits;
 
-pub fn check(tcx: TyCtxt<'_>) {
-    let mut orphan = OrphanChecker { tcx };
-    tcx.hir().visit_all_item_likes(&mut orphan);
+pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
+    let mut errors = Vec::new();
+    for (_trait, impls_of_trait) in tcx.all_local_trait_impls(()) {
+        for &impl_of_trait in impls_of_trait {
+            match orphan_check_impl(tcx, impl_of_trait) {
+                Ok(()) => {}
+                Err(ErrorReported) => errors.push(impl_of_trait),
+            }
+        }
+    }
+    tcx.arena.alloc_slice(&errors)
 }
 
-struct OrphanChecker<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
+#[instrument(skip(tcx), level = "debug")]
+fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorReported> {
+    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
+    let trait_def_id = trait_ref.def_id;
 
-impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
-    /// Checks exactly one impl for orphan rules and other such
-    /// restrictions. In this fn, it can happen that multiple errors
-    /// apply to a specific impl, so just return after reporting one
-    /// to prevent inundating the user with a bunch of similar error
-    /// reports.
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        // "Trait" impl
-        if let hir::ItemKind::Impl(hir::Impl {
-            generics, of_trait: Some(ref tr), self_ty, ..
-        }) = &item.kind
-        {
-            debug!(
-                "coherence2::orphan check: trait impl {}",
-                self.tcx.hir().node_to_string(item.hir_id())
-            );
-            let trait_ref = self.tcx.impl_trait_ref(item.def_id).unwrap();
-            let trait_def_id = trait_ref.def_id;
-            let sm = self.tcx.sess.source_map();
-            let sp = sm.guess_head_span(item.span);
-            match traits::orphan_check(self.tcx, item.def_id.to_def_id()) {
-                Ok(()) => {}
-                Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => {
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        sp,
-                        E0117,
-                        "only traits defined in the current crate can be implemented for \
-                         arbitrary types"
-                    );
-                    err.span_label(sp, "impl doesn't use only types from inside the current crate");
-                    for (ty, is_target_ty) in &tys {
-                        let mut ty = *ty;
-                        self.tcx.infer_ctxt().enter(|infcx| {
-                            // Remove the lifetimes unnecessary for this error.
-                            ty = infcx.freshen(ty);
-                        });
-                        ty = match ty.kind() {
-                            // Remove the type arguments from the output, as they are not relevant.
-                            // You can think of this as the reverse of `resolve_vars_if_possible`.
-                            // That way if we had `Vec<MyType>`, we will properly attribute the
-                            // problem to `Vec<T>` and avoid confusing the user if they were to see
-                            // `MyType` in the error.
-                            ty::Adt(def, _) => self.tcx.mk_adt(def, ty::List::empty()),
-                            _ => ty,
-                        };
-                        let this = "this".to_string();
-                        let (ty, postfix) = match &ty.kind() {
-                            ty::Slice(_) => (this, " because slices are always foreign"),
-                            ty::Array(..) => (this, " because arrays are always foreign"),
-                            ty::Tuple(..) => (this, " because tuples are always foreign"),
-                            _ => (format!("`{}`", ty), ""),
-                        };
-                        let msg = format!("{} is not defined in the current crate{}", ty, postfix);
-                        if *is_target_ty {
-                            // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
-                            err.span_label(self_ty.span, &msg);
-                        } else {
-                            // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
-                            err.span_label(tr.path.span, &msg);
-                        }
-                    }
-                    err.note("define and implement a trait or new type instead");
-                    err.emit();
-                    return;
-                }
-                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 item = tcx.hir().item(hir::ItemId { def_id });
+    let impl_ = match item.kind {
+        hir::ItemKind::Impl(ref impl_) => impl_,
+        _ => bug!("{:?} is not an impl: {:?}", def_id, item),
+    };
+    let sp = tcx.sess.source_map().guess_head_span(item.span);
+    let tr = impl_.of_trait.as_ref().unwrap();
+    match traits::orphan_check(tcx, item.def_id.to_def_id()) {
+        Ok(()) => {}
+        Err(err) => emit_orphan_check_error(
+            tcx,
+            sp,
+            tr.path.span,
+            impl_.self_ty.span,
+            &impl_.generics,
+            err,
+        )?,
+    }
+
+    // In addition to the above rules, we restrict impls of auto traits
+    // so that they can only be implemented on nominal types, such as structs,
+    // enums or foreign types. To see why this restriction exists, consider the
+    // following example (#22978). Imagine that crate A defines an auto trait
+    // `Foo` and a fn that operates on pairs of types:
+    //
+    // ```
+    // // Crate A
+    // auto trait Foo { }
+    // fn two_foos<A:Foo,B:Foo>(..) {
+    //     one_foo::<(A,B)>(..)
+    // }
+    // fn one_foo<T:Foo>(..) { .. }
+    // ```
+    //
+    // This type-checks fine; in particular the fn
+    // `two_foos` is able to conclude that `(A,B):Foo`
+    // because `A:Foo` and `B:Foo`.
+    //
+    // Now imagine that crate B comes along and does the following:
+    //
+    // ```
+    // struct A { }
+    // struct B { }
+    // impl Foo for A { }
+    // impl Foo for B { }
+    // impl !Send for (A, B) { }
+    // ```
+    //
+    // This final impl is legal according to the orphan
+    // rules, but it invalidates the reasoning from
+    // `two_foos` above.
+    debug!(
+        "trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
+        trait_ref,
+        trait_def_id,
+        tcx.trait_is_auto(trait_def_id)
+    );
+
+    if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
+        let self_ty = trait_ref.self_ty();
+        let opt_self_def_id = match *self_ty.kind() {
+            ty::Adt(self_def, _) => Some(self_def.did),
+            ty::Foreign(did) => Some(did),
+            _ => None,
+        };
 
-                    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 it is 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 it is implemented is local"
-                            ).note("only traits defined in the current crate can be \
-                                    implemented for a type parameter"
-                            ).emit();
-                        }
-                    };
-                    return;
+        let msg = match opt_self_def_id {
+            // We only want to permit nominal types, but not *all* nominal types.
+            // They must be local to the current crate, so that people
+            // can't do `unsafe impl Send for Rc<SomethingLocal>` or
+            // `impl !Send for Box<SomethingLocalAndSend>`.
+            Some(self_def_id) => {
+                if self_def_id.is_local() {
+                    None
+                } else {
+                    Some((
+                        format!(
+                            "cross-crate traits with a default impl, like `{}`, \
+                                    can only be implemented for a struct/enum type \
+                                    defined in the current crate",
+                            tcx.def_path_str(trait_def_id)
+                        ),
+                        "can't implement cross-crate trait for type in another crate",
+                    ))
                 }
             }
+            _ => Some((
+                format!(
+                    "cross-crate traits with a default impl, like `{}`, can \
+                                only be implemented for a struct/enum type, not `{}`",
+                    tcx.def_path_str(trait_def_id),
+                    self_ty
+                ),
+                "can't implement cross-crate trait with a default impl for \
+                        non-struct/enum type",
+            )),
+        };
 
-            // In addition to the above rules, we restrict impls of auto traits
-            // so that they can only be implemented on nominal types, such as structs,
-            // enums or foreign types. To see why this restriction exists, consider the
-            // following example (#22978). Imagine that crate A defines an auto trait
-            // `Foo` and a fn that operates on pairs of types:
-            //
-            // ```
-            // // Crate A
-            // auto trait Foo { }
-            // fn two_foos<A:Foo,B:Foo>(..) {
-            //     one_foo::<(A,B)>(..)
-            // }
-            // fn one_foo<T:Foo>(..) { .. }
-            // ```
-            //
-            // This type-checks fine; in particular the fn
-            // `two_foos` is able to conclude that `(A,B):Foo`
-            // because `A:Foo` and `B:Foo`.
-            //
-            // Now imagine that crate B comes along and does the following:
-            //
-            // ```
-            // struct A { }
-            // struct B { }
-            // impl Foo for A { }
-            // impl Foo for B { }
-            // impl !Send for (A, B) { }
-            // ```
-            //
-            // This final impl is legal according to the orphan
-            // rules, but it invalidates the reasoning from
-            // `two_foos` above.
-            debug!(
-                "trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
-                trait_ref,
-                trait_def_id,
-                self.tcx.trait_is_auto(trait_def_id)
+        if let Some((msg, label)) = msg {
+            struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
+            return Err(ErrorReported);
+        }
+    }
+
+    if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
+        tcx.sess
+            .struct_span_err(sp, "cannot implement trait on type alias impl trait")
+            .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
+            .emit();
+        return Err(ErrorReported);
+    }
+
+    Ok(())
+}
+
+fn emit_orphan_check_error(
+    tcx: TyCtxt<'tcx>,
+    sp: Span,
+    trait_span: Span,
+    self_ty_span: Span,
+    generics: &hir::Generics<'tcx>,
+    err: traits::OrphanCheckErr<'tcx>,
+) -> Result<!, ErrorReported> {
+    match err {
+        traits::OrphanCheckErr::NonLocalInputType(tys) => {
+            let mut err = struct_span_err!(
+                tcx.sess,
+                sp,
+                E0117,
+                "only traits defined in the current crate can be implemented for \
+                        arbitrary types"
             );
-            if self.tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
-                let self_ty = trait_ref.self_ty();
-                let opt_self_def_id = match *self_ty.kind() {
-                    ty::Adt(self_def, _) => Some(self_def.did),
-                    ty::Foreign(did) => Some(did),
-                    _ => None,
+            err.span_label(sp, "impl doesn't use only types from inside the current crate");
+            for (ty, is_target_ty) in &tys {
+                let mut ty = *ty;
+                tcx.infer_ctxt().enter(|infcx| {
+                    // Remove the lifetimes unnecessary for this error.
+                    ty = infcx.freshen(ty);
+                });
+                ty = match ty.kind() {
+                    // Remove the type arguments from the output, as they are not relevant.
+                    // You can think of this as the reverse of `resolve_vars_if_possible`.
+                    // That way if we had `Vec<MyType>`, we will properly attribute the
+                    // problem to `Vec<T>` and avoid confusing the user if they were to see
+                    // `MyType` in the error.
+                    ty::Adt(def, _) => tcx.mk_adt(def, ty::List::empty()),
+                    _ => ty,
                 };
-
-                let msg = match opt_self_def_id {
-                    // We only want to permit nominal types, but not *all* nominal types.
-                    // They must be local to the current crate, so that people
-                    // can't do `unsafe impl Send for Rc<SomethingLocal>` or
-                    // `impl !Send for Box<SomethingLocalAndSend>`.
-                    Some(self_def_id) => {
-                        if self_def_id.is_local() {
-                            None
-                        } else {
-                            Some((
-                                format!(
-                                    "cross-crate traits with a default impl, like `{}`, \
-                                         can only be implemented for a struct/enum type \
-                                         defined in the current crate",
-                                    self.tcx.def_path_str(trait_def_id)
-                                ),
-                                "can't implement cross-crate trait for type in another crate",
-                            ))
-                        }
-                    }
-                    _ => Some((
-                        format!(
-                            "cross-crate traits with a default impl, like `{}`, can \
-                                       only be implemented for a struct/enum type, not `{}`",
-                            self.tcx.def_path_str(trait_def_id),
-                            self_ty
-                        ),
-                        "can't implement cross-crate trait with a default impl for \
-                               non-struct/enum type",
-                    )),
+                let this = "this".to_string();
+                let (ty, postfix) = match &ty.kind() {
+                    ty::Slice(_) => (this, " because slices are always foreign"),
+                    ty::Array(..) => (this, " because arrays are always foreign"),
+                    ty::Tuple(..) => (this, " because tuples are always foreign"),
+                    _ => (format!("`{}`", ty), ""),
                 };
-
-                if let Some((msg, label)) = msg {
-                    struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
-                        .span_label(sp, label)
-                        .emit();
-                    return;
+                let msg = format!("{} is not defined in the current crate{}", ty, postfix);
+                if *is_target_ty {
+                    // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
+                    err.span_label(self_ty_span, &msg);
+                } else {
+                    // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
+                    err.span_label(trait_span, &msg);
+                }
+            }
+            err.note("define and implement a trait or new type instead");
+            err.emit()
+        }
+        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;
                 }
             }
 
-            if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
-                self.tcx
-                    .sess
-                    .struct_span_err(sp, "cannot implement trait on type alias impl trait")
-                    .span_note(self.tcx.def_span(def_id), "type alias impl trait defined here")
-                    .emit();
+            match local_type {
+                Some(local_type) => struct_span_err!(
+                    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 it is 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!(
+                    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 it is implemented is local",
+                )
+                .note(
+                    "only traits defined in the current crate can be \
+                        implemented for a type parameter",
+                )
+                .emit(),
             }
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
+    Err(ErrorReported)
 }
diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.rs b/src/test/ui/coherence/coherence-cross-crate-conflict.rs
index 648e290a4b8..588630957c9 100644
--- a/src/test/ui/coherence/coherence-cross-crate-conflict.rs
+++ b/src/test/ui/coherence/coherence-cross-crate-conflict.rs
@@ -6,9 +6,7 @@
 extern crate trait_impl_conflict;
 use trait_impl_conflict::Foo;
 
-impl<A> Foo for A {
-    //~^ ERROR E0119
-    //~| ERROR E0210
+impl<A> Foo for A { //~ ERROR E0210
 }
 
 fn main() {
diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr
index d0d86c72ffc..3d253d56a45 100644
--- a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr
+++ b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr
@@ -1,12 +1,3 @@
-error[E0119]: conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`
-  --> $DIR/coherence-cross-crate-conflict.rs:9:1
-   |
-LL | impl<A> Foo for A {
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `trait_impl_conflict`:
-           - impl Foo for isize;
-
 error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
   --> $DIR/coherence-cross-crate-conflict.rs:9:6
    |
@@ -16,7 +7,6 @@ LL | impl<A> Foo for A {
    = note: implementing a foreign trait is only possible if at least one of the types for which it is 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
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0119, E0210.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
index c364c707ff9..91289148079 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -1,15 +1,3 @@
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
-   |
-LL | impl !Marker1 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
-   |
-LL | impl !Marker2 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1
    |
@@ -33,6 +21,18 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | impl !Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
+   |
+LL | impl !Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
+   |
+LL | impl !Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
index b80429794f9..056198374a4 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
@@ -1,15 +1,3 @@
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
-   |
-LL | impl Marker1 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
-   |
-LL | impl Marker2 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1
    |
@@ -33,6 +21,18 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | unsafe impl Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
+   |
+LL | impl Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
+   |
+LL | impl Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
diff --git a/src/test/ui/coherence/coherence-impls-copy.rs b/src/test/ui/coherence/coherence-impls-copy.rs
index a86ca0e5eac..4204fecc37e 100644
--- a/src/test/ui/coherence/coherence-impls-copy.rs
+++ b/src/test/ui/coherence/coherence-impls-copy.rs
@@ -3,8 +3,7 @@
 use std::marker::Copy;
 
 impl Copy for i32 {}
-//~^ ERROR E0119
-//~| ERROR E0117
+//~^ ERROR E0117
 enum TestE {
   A
 }
@@ -32,7 +31,6 @@ impl Copy for [MyType] {}
 //~^ ERROR E0206
 //~| ERROR E0117
 impl Copy for &'static [NotSync] {}
-//~^ ERROR E0119
-//~| ERROR E0117
+//~^ ERROR E0117
 fn main() {
 }
diff --git a/src/test/ui/coherence/coherence-impls-copy.stderr b/src/test/ui/coherence/coherence-impls-copy.stderr
index 2ac0706d72e..a7d6968a296 100644
--- a/src/test/ui/coherence/coherence-impls-copy.stderr
+++ b/src/test/ui/coherence/coherence-impls-copy.stderr
@@ -1,50 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`
-  --> $DIR/coherence-impls-copy.rs:5:1
-   |
-LL | impl Copy for i32 {}
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl Copy for i32;
-
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`
-  --> $DIR/coherence-impls-copy.rs:29:1
-   |
-LL | impl Copy for &'static NotSync {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Copy for &T
-             where T: ?Sized;
-
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`
-  --> $DIR/coherence-impls-copy.rs:34:1
-   |
-LL | impl Copy for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Copy for &T
-             where T: ?Sized;
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/coherence-impls-copy.rs:22:15
-   |
-LL | impl Copy for &'static mut MyType {}
-   |               ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/coherence-impls-copy.rs:26:15
-   |
-LL | impl Copy for (MyType, MyType) {}
-   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/coherence-impls-copy.rs:31:15
-   |
-LL | impl Copy for [MyType] {}
-   |               ^^^^^^^^ type is not a structure or enumeration
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impls-copy.rs:5:1
    |
@@ -57,7 +10,7 @@ LL | impl Copy for i32 {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:26:1
+  --> $DIR/coherence-impls-copy.rs:25:1
    |
 LL | impl Copy for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^----------------
@@ -68,7 +21,7 @@ LL | impl Copy for (MyType, MyType) {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:31:1
+  --> $DIR/coherence-impls-copy.rs:30:1
    |
 LL | impl Copy for [MyType] {}
    | ^^^^^^^^^^^^^^--------
@@ -79,7 +32,7 @@ LL | impl Copy for [MyType] {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:34:1
+  --> $DIR/coherence-impls-copy.rs:33:1
    |
 LL | impl Copy for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^------------------
@@ -89,7 +42,35 @@ LL | impl Copy for &'static [NotSync] {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 10 previous errors
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`
+  --> $DIR/coherence-impls-copy.rs:28:1
+   |
+LL | impl Copy for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> Copy for &T
+             where T: ?Sized;
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:21:15
+   |
+LL | impl Copy for &'static mut MyType {}
+   |               ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:25:15
+   |
+LL | impl Copy for (MyType, MyType) {}
+   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:30:15
+   |
+LL | impl Copy for [MyType] {}
+   |               ^^^^^^^^ type is not a structure or enumeration
+
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0117, E0119, E0206.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-send.rs b/src/test/ui/coherence/coherence-impls-send.rs
index e00cb9a7c5b..b7b57c602b8 100644
--- a/src/test/ui/coherence/coherence-impls-send.rs
+++ b/src/test/ui/coherence/coherence-impls-send.rs
@@ -23,7 +23,6 @@ unsafe impl Send for [MyType] {}
 //~^ ERROR E0117
 
 unsafe impl Send for &'static [NotSync] {}
-//~^ ERROR conflicting implementations of trait
-//~| ERROR only traits defined in the current crate
+//~^ ERROR only traits defined in the current crate
 
 fn main() {}
diff --git a/src/test/ui/coherence/coherence-impls-send.stderr b/src/test/ui/coherence/coherence-impls-send.stderr
index 46e9e7e986c..dd1fd1b0dce 100644
--- a/src/test/ui/coherence/coherence-impls-send.stderr
+++ b/src/test/ui/coherence/coherence-impls-send.stderr
@@ -1,14 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::marker::Send` for type `&[NotSync]`
-  --> $DIR/coherence-impls-send.rs:25:1
-   |
-LL | unsafe impl Send for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Send for &T
-             where T: Sync, T: ?Sized;
-   = note: upstream crates may add a new impl of trait `std::marker::Sync` for type `[NotSync]` in future versions
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impls-send.rs:16:1
    |
@@ -48,7 +37,7 @@ LL | unsafe impl Send for &'static [NotSync] {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0117, E0119, E0321.
+Some errors have detailed explanations: E0117, E0321.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-sized.stderr b/src/test/ui/coherence/coherence-impls-sized.stderr
index 3b0a9fc60a2..9cf5ed38c9c 100644
--- a/src/test/ui/coherence/coherence-impls-sized.stderr
+++ b/src/test/ui/coherence/coherence-impls-sized.stderr
@@ -1,3 +1,36 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:20:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^----------------
+   | |              |
+   | |              this is not defined in the current crate because tuples are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^--------
+   | |              |
+   | |              this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:31:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^------------------
+   | |              |
+   | |              this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error[E0322]: explicit impls for the `Sized` trait are not permitted
   --> $DIR/coherence-impls-sized.rs:14:1
    |
@@ -34,39 +67,6 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted
 LL | impl Sized for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:20:1
-   |
-LL | impl Sized for (MyType, MyType) {}
-   | ^^^^^^^^^^^^^^^----------------
-   | |              |
-   | |              this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:27:1
-   |
-LL | impl Sized for [MyType] {}
-   | ^^^^^^^^^^^^^^^--------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:31:1
-   |
-LL | impl Sized for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^------------------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
 error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0117, E0322.
diff --git a/src/test/ui/coherence/coherence-orphan.stderr b/src/test/ui/coherence/coherence-orphan.stderr
index 52d2cc88cbe..051a519ee14 100644
--- a/src/test/ui/coherence/coherence-orphan.stderr
+++ b/src/test/ui/coherence/coherence-orphan.stderr
@@ -1,22 +1,22 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-orphan.rs:10:1
+  --> $DIR/coherence-orphan.rs:17:1
    |
-LL | impl TheTrait<usize> for isize { }
-   | ^^^^^---------------^^^^^-----
-   | |    |                   |
-   | |    |                   `isize` is not defined in the current crate
-   | |    `usize` is not defined in the current crate
+LL | impl !Send for Vec<isize> { }
+   | ^^^^^^^^^^^^^^^----------
+   | |              |
+   | |              `Vec` is not defined in the current crate
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-orphan.rs:17:1
+  --> $DIR/coherence-orphan.rs:10:1
    |
-LL | impl !Send for Vec<isize> { }
-   | ^^^^^^^^^^^^^^^----------
-   | |              |
-   | |              `Vec` is not defined in the current crate
+LL | impl TheTrait<usize> for isize { }
+   | ^^^^^---------------^^^^^-----
+   | |    |                   |
+   | |    |                   `isize` is not defined in the current crate
+   | |    `usize` is not defined in the current crate
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr
index 3991c44f2ed..e52728f3781 100644
--- a/src/test/ui/dropck/drop-on-non-struct.stderr
+++ b/src/test/ui/dropck/drop-on-non-struct.stderr
@@ -4,12 +4,6 @@ error[E0412]: cannot find type `Nonexistent` in this scope
 LL | impl Drop for Nonexistent {
    |               ^^^^^^^^^^^ not found in this scope
 
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
-  --> $DIR/drop-on-non-struct.rs:1:19
-   |
-LL | impl<'a> Drop for &'a mut isize {
-   |                   ^^^^^^^^^^^^^ must be a struct, enum, or union
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/drop-on-non-struct.rs:1:1
    |
@@ -21,6 +15,12 @@ LL | impl<'a> Drop for &'a mut isize {
    |
    = note: define and implement a trait or new type instead
 
+error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+  --> $DIR/drop-on-non-struct.rs:1:19
+   |
+LL | impl<'a> Drop for &'a mut isize {
+   |                   ^^^^^^^^^^^^^ must be a struct, enum, or union
+
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0117, E0120, E0412.
diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr
index b48a1d8e50d..cdbafff2a20 100644
--- a/src/test/ui/error-codes/E0117.stderr
+++ b/src/test/ui/error-codes/E0117.stderr
@@ -1,9 +1,3 @@
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
-  --> $DIR/E0117.rs:1:15
-   |
-LL | impl Drop for u32 {}
-   |               ^^^ must be a struct, enum, or union
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/E0117.rs:1:1
    |
@@ -15,6 +9,12 @@ LL | impl Drop for u32 {}
    |
    = note: define and implement a trait or new type instead
 
+error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+  --> $DIR/E0117.rs:1:15
+   |
+LL | impl Drop for u32 {}
+   |               ^^^ must be a struct, enum, or union
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0117, E0120.
diff --git a/src/test/ui/error-codes/e0119/complex-impl.rs b/src/test/ui/error-codes/e0119/complex-impl.rs
index 7dbf93ada5e..9149e4ce58e 100644
--- a/src/test/ui/error-codes/e0119/complex-impl.rs
+++ b/src/test/ui/error-codes/e0119/complex-impl.rs
@@ -7,6 +7,5 @@ use complex_impl_support::{External, M};
 struct Q;
 
 impl<R> External for (Q, R) {} //~ ERROR only traits defined
-//~^ ERROR conflicting implementations of trait
 
 fn main() {}
diff --git a/src/test/ui/error-codes/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr
index 6a1a502749a..654073eec26 100644
--- a/src/test/ui/error-codes/e0119/complex-impl.stderr
+++ b/src/test/ui/error-codes/e0119/complex-impl.stderr
@@ -1,13 +1,3 @@
-error[E0119]: conflicting implementations of trait `complex_impl_support::External` for type `(Q, complex_impl_support::M<'_, '_, '_, std::boxed::Box<_>, _, _>)`
-  --> $DIR/complex-impl.rs:9:1
-   |
-LL | impl<R> External for (Q, R) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `complex_impl_support`:
-           - impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>)
-             where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/complex-impl.rs:9:1
    |
@@ -19,7 +9,6 @@ LL | impl<R> External for (Q, R) {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0117, E0119.
-For more information about an error, try `rustc --explain E0117`.
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/error-codes/e0119/issue-28981.rs b/src/test/ui/error-codes/e0119/issue-28981.rs
index c31b212b25a..5fb7e9a9913 100644
--- a/src/test/ui/error-codes/e0119/issue-28981.rs
+++ b/src/test/ui/error-codes/e0119/issue-28981.rs
@@ -3,6 +3,5 @@ use std::ops::Deref;
 struct Foo;
 
 impl<Foo> Deref for Foo { } //~ ERROR must be used
-//~^ ERROR conflicting implementations
 
 fn main() {}
diff --git a/src/test/ui/error-codes/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr
index 56e8e1eb540..97b570bc7ac 100644
--- a/src/test/ui/error-codes/e0119/issue-28981.stderr
+++ b/src/test/ui/error-codes/e0119/issue-28981.stderr
@@ -1,13 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&_`
-  --> $DIR/issue-28981.rs:5:1
-   |
-LL | impl<Foo> Deref for Foo { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Deref for &T
-             where T: ?Sized;
-
 error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g., `MyStruct<Foo>`)
   --> $DIR/issue-28981.rs:5:6
    |
@@ -17,7 +7,6 @@ LL | impl<Foo> Deref for Foo { }
    = note: implementing a foreign trait is only possible if at least one of the types for which it is 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
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0119, E0210.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/issues/issue-41974.rs b/src/test/ui/issues/issue-41974.rs
index 7875b432d7b..10c363479a3 100644
--- a/src/test/ui/issues/issue-41974.rs
+++ b/src/test/ui/issues/issue-41974.rs
@@ -4,9 +4,9 @@ struct Flags;
 trait A {
 }
 
-impl<T> Drop for T where T: A { //~ ERROR E0119
-                                //~^ ERROR E0120
-                                //~| ERROR E0210
+impl<T> Drop for T where T: A {
+    //~^ ERROR E0120
+    //~| ERROR E0210
     fn drop(&mut self) {
     }
 }
diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr
index 11d77857d60..fcbb4014025 100644
--- a/src/test/ui/issues/issue-41974.stderr
+++ b/src/test/ui/issues/issue-41974.stderr
@@ -1,13 +1,11 @@
-error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_, _>`
-  --> $DIR/issue-41974.rs:7:1
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/issue-41974.rs:7:6
    |
 LL | impl<T> Drop for T where T: A {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^ type parameter `T` must be used as the type parameter for some local type
    |
-   = note: conflicting implementation in crate `alloc`:
-           - impl<T, A> Drop for Box<T, A>
-             where A: Allocator, T: ?Sized;
-   = note: downstream crates may implement trait `A` for type `std::boxed::Box<_, _>`
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
   --> $DIR/issue-41974.rs:7:18
@@ -15,16 +13,7 @@ error[E0120]: the `Drop` trait may only be implemented for structs, enums, and u
 LL | impl<T> Drop for T where T: A {
    |                  ^ must be a struct, enum, or union
 
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
-  --> $DIR/issue-41974.rs:7:6
-   |
-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 it is 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
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0119, E0120, E0210.
-For more information about an error, try `rustc --explain E0119`.
+Some errors have detailed explanations: E0120, E0210.
+For more information about an error, try `rustc --explain E0120`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
index 4b2f049b99d..961968186de 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
@@ -2,9 +2,8 @@
 
 pub struct Int(i32);
 
-impl const std::ops::Add for i32 {
-    //~^ ERROR conflicting implementations of trait
-    //~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+impl const std::ops::Add for i32 { //~ ERROR type annotations needed
+    //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
@@ -12,7 +11,7 @@ impl const std::ops::Add for i32 {
     }
 }
 
-impl std::ops::Add for Int {
+impl std::ops::Add for Int { //~ ERROR type annotations needed
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
@@ -20,7 +19,7 @@ impl std::ops::Add for Int {
     }
 }
 
-impl const std::ops::Add for Int {
+impl const std::ops::Add for Int { //~ ERROR type annotations needed
     //~^ ERROR conflicting implementations of trait
     type Output = Self;
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
index a0960a21d46..785095c29ae 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
@@ -1,14 +1,17 @@
-error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^-------------^^^^^---
+   | |          |                 |
+   | |          |                 `i32` is not defined in the current crate
+   | |          `i32` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
    |
-   = note: conflicting implementation in crate `core`:
-           - impl Add for i32;
+   = note: define and implement a trait or new type instead
 
 error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`
-  --> $DIR/const-and-non-const-impl.rs:23:1
+  --> $DIR/const-and-non-const-impl.rs:22:1
    |
 LL | impl std::ops::Add for Int {
    | -------------------------- first implementation here
@@ -16,19 +19,83 @@ LL | impl std::ops::Add for Int {
 LL | impl const std::ops::Add for Int {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0283]: type annotations needed
+  --> $DIR/const-and-non-const-impl.rs:5:12
+   |
+LL | impl const std::ops::Add for i32 {
+   |            ^^^^^^^^^^^^^ cannot infer type for type `i32`
+   |
+note: multiple `impl`s satisfying `i32: Add` found
   --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
-   | ^^^^^^^^^^^-------------^^^^^---
-   | |          |                 |
-   | |          |                 `i32` is not defined in the current crate
-   | |          `i32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: and another `impl` found in the `core` crate: `impl Add for i32;`
+note: required by a bound in `Add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
    |
-   = note: define and implement a trait or new type instead
+LL | / pub trait Add<Rhs = Self> {
+LL | |     /// The resulting type after applying the `+` operator.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Output;
+...  |
+LL | |     fn add(self, rhs: Rhs) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `Add`
+
+error[E0283]: type annotations needed
+  --> $DIR/const-and-non-const-impl.rs:14:6
+   |
+LL | impl std::ops::Add for Int {
+   |      ^^^^^^^^^^^^^ cannot infer type for struct `Int`
+   |
+note: multiple `impl`s satisfying `Int: Add` found
+  --> $DIR/const-and-non-const-impl.rs:14:1
+   |
+LL | impl std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl const std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `Add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL | / pub trait Add<Rhs = Self> {
+LL | |     /// The resulting type after applying the `+` operator.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Output;
+...  |
+LL | |     fn add(self, rhs: Rhs) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `Add`
+
+error[E0283]: type annotations needed
+  --> $DIR/const-and-non-const-impl.rs:22:12
+   |
+LL | impl const std::ops::Add for Int {
+   |            ^^^^^^^^^^^^^ cannot infer type for struct `Int`
+   |
+note: multiple `impl`s satisfying `Int: Add` found
+  --> $DIR/const-and-non-const-impl.rs:14:1
+   |
+LL | impl std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl const std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `Add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL | / pub trait Add<Rhs = Self> {
+LL | |     /// The resulting type after applying the `+` operator.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Output;
+...  |
+LL | |     fn add(self, rhs: Rhs) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `Add`
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0117, E0119.
+Some errors have detailed explanations: E0117, E0119, E0283.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr
index 0ab39ae6672..6a3498a3893 100644
--- a/src/test/ui/traits/alias/issue-83613.stderr
+++ b/src/test/ui/traits/alias/issue-83613.stderr
@@ -1,11 +1,3 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
-  --> $DIR/issue-83613.rs:10:1
-   |
-LL | impl<T: Send> AnotherTrait for T {}
-   | -------------------------------- first implementation here
-LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait`
-
 error: cannot implement trait on type alias impl trait
   --> $DIR/issue-83613.rs:10:1
    |
@@ -18,6 +10,14 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
+  --> $DIR/issue-83613.rs:10:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+LL | impl AnotherTrait for OpaqueType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait`
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr
index 0150ff41303..49a9f479368 100644
--- a/src/test/ui/traits/issue-78372.stderr
+++ b/src/test/ui/traits/issue-78372.stderr
@@ -50,12 +50,6 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    |
    = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
 
-error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
-  --> $DIR/issue-78372.rs:3:1
-   |
-LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`)
   --> $DIR/issue-78372.rs:3:6
    |
@@ -65,6 +59,12 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    = note: implementing a foreign trait is only possible if at least one of the types for which it is 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[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+  --> $DIR/issue-78372.rs:3:1
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0210, E0378, E0412, E0658.
diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
index c46c4715924..685d76ee36f 100644
--- a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
+++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
@@ -8,8 +8,7 @@ trait MyTrait {}
 impl MyTrait for () {}
 
 impl<F> FnOnce<()> for &F {
-    //~^ ERROR conflicting implementations
-    //~| ERROR type parameter `F` must be used
+    //~^ ERROR type parameter `F` must be used
     type Output = impl MyTrait;
     extern "rust-call" fn call_once(self, _: ()) -> Self::Output {}
 }
diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
index e1e259187f5..b93ea955c89 100644
--- a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
+++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
@@ -1,13 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_`
-  --> $DIR/incoherent-assoc-imp-trait.rs:10:1
-   |
-LL | impl<F> FnOnce<()> for &F {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<A, F> FnOnce<A> for &F
-             where F: Fn<A>, F: ?Sized;
-
 error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`)
   --> $DIR/incoherent-assoc-imp-trait.rs:10:6
    |
@@ -17,7 +7,6 @@ LL | impl<F> FnOnce<()> for &F {
    = note: implementing a foreign trait is only possible if at least one of the types for which it is 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
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0119, E0210.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0210`.