about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2020-01-08 14:10:59 -0500
committerNiko Matsakis <niko@alum.mit.edu>2020-03-26 06:52:26 -0400
commit65071708f8fe72dd2103c6eace0eb6802a6acf03 (patch)
tree912d748e82574d835e72d9d69d4cd3b5a5f1d6a3
parente8a05e201ee6cea12fe05e4271e91fd40c2fb235 (diff)
downloadrust-65071708f8fe72dd2103c6eace0eb6802a6acf03.tar.gz
rust-65071708f8fe72dd2103c6eace0eb6802a6acf03.zip
make a custom error for overlap with negative impls
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0751.md12
-rw-r--r--src/librustc_trait_selection/traits/specialize/mod.rs245
-rw-r--r--src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs8
-rw-r--r--src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr21
-rw-r--r--src/test/ui/issues/issue-33140-hack-boundaries.rs28
-rw-r--r--src/test/ui/issues/issue-33140-hack-boundaries.stderr25
-rw-r--r--src/test/ui/specialization/specialization-overlap-negative.rs2
-rw-r--r--src/test/ui/specialization/specialization-overlap-negative.stderr8
-rw-r--r--src/test/ui/specialization/specialization-polarity.rs4
-rw-r--r--src/test/ui/specialization/specialization-polarity.stderr14
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs6
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr10
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive.rs14
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive.stderr12
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs4
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr10
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs4
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr10
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.rs8
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.stderr12
21 files changed, 271 insertions, 187 deletions
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index bff20c2a62c..fdcf3d63957 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -427,6 +427,7 @@ E0747: include_str!("./error_codes/E0747.md"),
 E0748: include_str!("./error_codes/E0748.md"),
 E0749: include_str!("./error_codes/E0749.md"),
 E0750: include_str!("./error_codes/E0750.md"),
+E0751: include_str!("./error_codes/E0751.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0751.md b/src/librustc_error_codes/error_codes/E0751.md
new file mode 100644
index 00000000000..a440f82e4b6
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0751.md
@@ -0,0 +1,12 @@
+There are both a positive and negative trait implementation for the same type.
+
+Erroneous code example:
+
+```compile_fail,E0748
+trait MyTrait {}
+impl MyTrait for i32 { }
+impl !MyTrait for i32 { }
+```
+
+Negative implementations are a promise that the trait will never be
+implemented for the given types.
diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs
index 0cc5032d74e..732716ef865 100644
--- a/src/librustc_trait_selection/traits/specialize/mod.rs
+++ b/src/librustc_trait_selection/traits/specialize/mod.rs
@@ -324,86 +324,7 @@ pub(super) fn specialization_graph_provider(
             };
 
             if let Some(overlap) = overlap {
-                let impl_span =
-                    tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap());
-
-                // Work to be done after we've built the DiagnosticBuilder. We have to define it
-                // now because the struct_lint methods don't return back the DiagnosticBuilder
-                // that's passed in.
-                let decorate = |err: LintDiagnosticBuilder<'_>| {
-                    let msg = format!(
-                        "conflicting implementations of trait `{}`{}:{}",
-                        overlap.trait_desc,
-                        overlap
-                            .self_desc
-                            .clone()
-                            .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }),
-                        match used_to_be_allowed {
-                            Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)",
-                            _ => "",
-                        }
-                    );
-                    let mut err = err.build(&msg);
-                    match tcx.span_of_impl(overlap.with_impl) {
-                        Ok(span) => {
-                            err.span_label(
-                                tcx.sess.source_map().guess_head_span(span),
-                                "first implementation here".to_string(),
-                            );
-
-                            err.span_label(
-                                impl_span,
-                                format!(
-                                    "conflicting implementation{}",
-                                    overlap
-                                        .self_desc
-                                        .map_or(String::new(), |ty| format!(" for `{}`", ty))
-                                ),
-                            );
-                        }
-                        Err(cname) => {
-                            let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
-                                Some(s) => format!(
-                                    "conflicting implementation in crate `{}`:\n- {}",
-                                    cname, s
-                                ),
-                                None => format!("conflicting implementation in crate `{}`", cname),
-                            };
-                            err.note(&msg);
-                        }
-                    }
-
-                    for cause in &overlap.intercrate_ambiguity_causes {
-                        cause.add_intercrate_ambiguity_hint(&mut err);
-                    }
-
-                    if overlap.involves_placeholder {
-                        coherence::add_placeholder_note(&mut err);
-                    }
-                    err.emit()
-                };
-
-                match used_to_be_allowed {
-                    None => {
-                        sg.has_errored = true;
-                        let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
-                        decorate(LintDiagnosticBuilder::new(err));
-                    }
-                    Some(kind) => {
-                        let lint = match kind {
-                            FutureCompatOverlapErrorKind::Issue33140 => {
-                                ORDER_DEPENDENT_TRAIT_OBJECTS
-                            }
-                            FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
-                        };
-                        tcx.struct_span_lint_hir(
-                            lint,
-                            tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
-                            impl_span,
-                            decorate,
-                        )
-                    }
-                };
+                report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg);
             }
         } else {
             let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
@@ -414,6 +335,170 @@ pub(super) fn specialization_graph_provider(
     tcx.arena.alloc(sg)
 }
 
+fn report_overlap_conflict(
+    tcx: TyCtxt<'_>,
+    overlap: OverlapError,
+    impl_def_id: DefId,
+    used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
+    sg: &mut specialization_graph::Graph,
+) {
+    let impl_polarity = tcx.impl_polarity(impl_def_id);
+    let other_polarity = tcx.impl_polarity(overlap.with_impl);
+    match (impl_polarity, other_polarity) {
+        (ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => {
+            report_negative_positive_conflict(
+                tcx,
+                &overlap,
+                impl_def_id,
+                impl_def_id,
+                overlap.with_impl,
+                sg,
+            );
+        }
+
+        (ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => {
+            report_negative_positive_conflict(
+                tcx,
+                &overlap,
+                impl_def_id,
+                overlap.with_impl,
+                impl_def_id,
+                sg,
+            );
+        }
+
+        _ => {
+            report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg);
+        }
+    }
+}
+
+fn report_negative_positive_conflict(
+    tcx: TyCtxt<'_>,
+    overlap: &OverlapError,
+    local_impl_def_id: DefId,
+    negative_impl_def_id: DefId,
+    positive_impl_def_id: DefId,
+    sg: &mut specialization_graph::Graph,
+) {
+    let impl_span =
+        tcx.sess.source_map().guess_head_span(tcx.span_of_impl(local_impl_def_id).unwrap());
+
+    let mut err = struct_span_err!(
+        tcx.sess,
+        impl_span,
+        E0748,
+        "found both positive and negative implementation of trait `{}`{}:",
+        overlap.trait_desc,
+        overlap.self_desc.clone().map_or(String::new(), |ty| format!(" for type `{}`", ty))
+    );
+
+    match tcx.span_of_impl(negative_impl_def_id) {
+        Ok(span) => {
+            err.span_label(
+                tcx.sess.source_map().guess_head_span(span),
+                "negative implementation here".to_string(),
+            );
+        }
+        Err(cname) => {
+            err.note(&format!("negative implementation in crate `{}`", cname));
+        }
+    }
+
+    match tcx.span_of_impl(positive_impl_def_id) {
+        Ok(span) => {
+            err.span_label(
+                tcx.sess.source_map().guess_head_span(span),
+                "positive implementation here".to_string(),
+            );
+        }
+        Err(cname) => {
+            err.note(&format!("positive implementation in crate `{}`", cname));
+        }
+    }
+
+    sg.has_errored = true;
+    err.emit();
+}
+
+fn report_conflicting_impls(
+    tcx: TyCtxt<'_>,
+    overlap: OverlapError,
+    impl_def_id: DefId,
+    used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
+    sg: &mut specialization_graph::Graph,
+) {
+    let impl_span = tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap());
+
+    // Work to be done after we've built the DiagnosticBuilder. We have to define it
+    // now because the struct_lint methods don't return back the DiagnosticBuilder
+    // that's passed in.
+    let decorate = |err: LintDiagnosticBuilder<'_>| {
+        let msg = format!(
+            "conflicting implementations of trait `{}`{}:{}",
+            overlap.trait_desc,
+            overlap.self_desc.clone().map_or(String::new(), |ty| { format!(" for type `{}`", ty) }),
+            match used_to_be_allowed {
+                Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)",
+                _ => "",
+            }
+        );
+        let mut err = err.build(&msg);
+        match tcx.span_of_impl(overlap.with_impl) {
+            Ok(span) => {
+                err.span_label(
+                    tcx.sess.source_map().guess_head_span(span),
+                    "first implementation here".to_string(),
+                );
+
+                err.span_label(
+                    impl_span,
+                    format!(
+                        "conflicting implementation{}",
+                        overlap.self_desc.map_or(String::new(), |ty| format!(" for `{}`", ty))
+                    ),
+                );
+            }
+            Err(cname) => {
+                let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
+                    Some(s) => format!("conflicting implementation in crate `{}`:\n- {}", cname, s),
+                    None => format!("conflicting implementation in crate `{}`", cname),
+                };
+                err.note(&msg);
+            }
+        }
+
+        for cause in &overlap.intercrate_ambiguity_causes {
+            cause.add_intercrate_ambiguity_hint(&mut err);
+        }
+
+        if overlap.involves_placeholder {
+            coherence::add_placeholder_note(&mut err);
+        }
+        err.emit()
+    };
+
+    match used_to_be_allowed {
+        None => {
+            sg.has_errored = true;
+            let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
+            decorate(LintDiagnosticBuilder::new(err));
+        }
+        Some(kind) => {
+            let lint = match kind {
+                FutureCompatOverlapErrorKind::Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS,
+                FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
+            };
+            tcx.struct_span_lint_hir(
+                lint,
+                tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
+                impl_span,
+                decorate,
+            )
+        }
+    };
+}
+
 /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
 /// string.
 fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
index b4f5f9ef56b..0fabb5ec91d 100644
--- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
@@ -6,13 +6,11 @@ trait MyTrait {}
 
 struct TestType<T>(::std::marker::PhantomData<T>);
 
-unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
+unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
 
-impl<T: MyTrait> !Send for TestType<T> {}
-//~^ ERROR conflicting implementations
+impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR found both positive and negative implementation
 
-unsafe impl<T:'static> Send for TestType<T> {}
-//~^ ERROR conflicting implementations
+unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
 
 impl !Send for TestType<i32> {}
 
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
index 25d3d3ee997..5081536b702 100644
--- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
@@ -1,21 +1,22 @@
-error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
+error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`:
   --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:1
    |
-LL | unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
-   | ---------------------------------------------------- first implementation here
+LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
+   | ------------------------------------------------------ positive implementation here
 LL | 
 LL | impl<T: MyTrait> !Send for TestType<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
-  --> $DIR/coherence-conflicting-negative-trait-impl.rs:14:1
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1
    |
-LL | unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
-   | ---------------------------------------------------- first implementation here
+LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
+   | ------------------------------------------------------ first implementation here
 ...
-LL | unsafe impl<T:'static> Send for TestType<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+LL | unsafe impl<T: 'static> Send for TestType<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0119`.
+Some errors have detailed explanations: E0119, E0748.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs
index fbdef51c132..5aba886273f 100644
--- a/src/test/ui/issues/issue-33140-hack-boundaries.rs
+++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs
@@ -4,8 +4,7 @@
 // Check that the issue #33140 hack does not allow unintended things.
 
 // OK
-trait Trait0 {
-}
+trait Trait0 {}
 
 impl Trait0 for dyn Send {}
 impl Trait0 for dyn Send {}
@@ -20,58 +19,49 @@ impl Trait1 for dyn Send {}
 //~^ ERROR E0119
 
 // Problem 2: negative impl
-trait Trait2 {
-}
+trait Trait2 {}
 
 impl Trait2 for dyn Send {}
 impl !Trait2 for dyn Send {}
-//~^ ERROR E0119
-
+//~^ ERROR E0748
 
 // Problem 3: type parameter
-trait Trait3<T: ?Sized> {
-}
+trait Trait3<T: ?Sized> {}
 
 impl Trait3<dyn Sync> for dyn Send {}
 impl Trait3<dyn Sync> for dyn Send {}
 //~^ ERROR E0119
 
 // Problem 4a: not a trait object - generic
-trait Trait4a {
-}
+trait Trait4a {}
 
 impl<T: ?Sized> Trait4a for T {}
 impl Trait4a for dyn Send {}
 //~^ ERROR E0119
 
 // Problem 4b: not a trait object - misc
-trait Trait4b {
-}
+trait Trait4b {}
 
 impl Trait4b for () {}
 impl Trait4b for () {}
 //~^ ERROR E0119
 
 // Problem 4c: not a principal-less trait object
-trait Trait4c {
-}
+trait Trait4c {}
 
 impl Trait4c for dyn Trait1 + Send {}
 impl Trait4c for dyn Trait1 + Send {}
 //~^ ERROR E0119
 
 // Problem 4d: lifetimes
-trait Trait4d {
-}
+trait Trait4d {}
 
 impl<'a> Trait4d for dyn Send + 'a {}
 impl<'a> Trait4d for dyn Send + 'a {}
 //~^ ERROR E0119
 
-
 // Problem 5: where-clauses
-trait Trait5 {
-}
+trait Trait5 {}
 
 impl Trait5 for dyn Send {}
 impl Trait5 for dyn Send where u32: Copy {}
diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr
index 95aaa55ba7c..b3bf34a2a90 100644
--- a/src/test/ui/issues/issue-33140-hack-boundaries.stderr
+++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr
@@ -1,21 +1,21 @@
 error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`:
-  --> $DIR/issue-33140-hack-boundaries.rs:19:1
+  --> $DIR/issue-33140-hack-boundaries.rs:18:1
    |
 LL | impl Trait1 for dyn Send {}
    | ------------------------ first implementation here
 LL | impl Trait1 for dyn Send {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
 
-error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + 'static)`:
-  --> $DIR/issue-33140-hack-boundaries.rs:27:1
+error[E0748]: found both positive and negative implementation of trait `Trait2` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:25:1
    |
 LL | impl Trait2 for dyn Send {}
-   | ------------------------ first implementation here
+   | ------------------------ positive implementation here
 LL | impl !Trait2 for dyn Send {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`:
-  --> $DIR/issue-33140-hack-boundaries.rs:36:1
+  --> $DIR/issue-33140-hack-boundaries.rs:32:1
    |
 LL | impl Trait3<dyn Sync> for dyn Send {}
    | ---------------------------------- first implementation here
@@ -23,7 +23,7 @@ LL | impl Trait3<dyn Sync> for dyn Send {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
 
 error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`:
-  --> $DIR/issue-33140-hack-boundaries.rs:44:1
+  --> $DIR/issue-33140-hack-boundaries.rs:39:1
    |
 LL | impl<T: ?Sized> Trait4a for T {}
    | ----------------------------- first implementation here
@@ -31,7 +31,7 @@ LL | impl Trait4a for dyn Send {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
 
 error[E0119]: conflicting implementations of trait `Trait4b` for type `()`:
-  --> $DIR/issue-33140-hack-boundaries.rs:52:1
+  --> $DIR/issue-33140-hack-boundaries.rs:46:1
    |
 LL | impl Trait4b for () {}
    | ------------------- first implementation here
@@ -39,7 +39,7 @@ LL | impl Trait4b for () {}
    | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
 
 error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`:
-  --> $DIR/issue-33140-hack-boundaries.rs:60:1
+  --> $DIR/issue-33140-hack-boundaries.rs:53:1
    |
 LL | impl Trait4c for dyn Trait1 + Send {}
    | ---------------------------------- first implementation here
@@ -47,7 +47,7 @@ LL | impl Trait4c for dyn Trait1 + Send {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)`
 
 error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`:
-  --> $DIR/issue-33140-hack-boundaries.rs:68:1
+  --> $DIR/issue-33140-hack-boundaries.rs:60:1
    |
 LL | impl<'a> Trait4d for dyn Send + 'a {}
    | ---------------------------------- first implementation here
@@ -55,7 +55,7 @@ LL | impl<'a> Trait4d for dyn Send + 'a {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send`
 
 error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`:
-  --> $DIR/issue-33140-hack-boundaries.rs:77:1
+  --> $DIR/issue-33140-hack-boundaries.rs:67:1
    |
 LL | impl Trait5 for dyn Send {}
    | ------------------------ first implementation here
@@ -64,4 +64,5 @@ LL | impl Trait5 for dyn Send where u32: Copy {}
 
 error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0119`.
+Some errors have detailed explanations: E0119, E0748.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs
index af80d6686e3..4f5f65dafaa 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.rs
+++ b/src/test/ui/specialization/specialization-overlap-negative.rs
@@ -6,6 +6,6 @@ trait MyTrait {}
 struct TestType<T>(::std::marker::PhantomData<T>);
 
 unsafe impl<T: Clone> Send for TestType<T> {}
-impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0119
+impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0748
 
 fn main() {}
diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr
index 947aad824ea..cbc7271b199 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.stderr
+++ b/src/test/ui/specialization/specialization-overlap-negative.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
+error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`:
   --> $DIR/specialization-overlap-negative.rs:9:1
    |
 LL | unsafe impl<T: Clone> Send for TestType<T> {}
-   | ------------------------------------------ first implementation here
+   | ------------------------------------------ positive implementation here
 LL | impl<T: MyTrait> !Send for TestType<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs
index d5744806745..fd0671ad09e 100644
--- a/src/test/ui/specialization/specialization-polarity.rs
+++ b/src/test/ui/specialization/specialization-polarity.rs
@@ -6,11 +6,11 @@
 auto trait Foo {}
 
 impl<T> Foo for T {}
-impl !Foo for u8 {} //~ ERROR E0119
+impl !Foo for u8 {} //~ ERROR E0748
 
 auto trait Bar {}
 
 impl<T> !Bar for T {}
-impl Bar for u8 {} //~ ERROR E0119
+impl Bar for u8 {} //~ ERROR E0748
 
 fn main() {}
diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr
index bc1b2aeb70f..c6e7f193d01 100644
--- a/src/test/ui/specialization/specialization-polarity.stderr
+++ b/src/test/ui/specialization/specialization-polarity.stderr
@@ -1,19 +1,19 @@
-error[E0119]: conflicting implementations of trait `Foo` for type `u8`:
+error[E0748]: found both positive and negative implementation of trait `Foo` for type `u8`:
   --> $DIR/specialization-polarity.rs:9:1
    |
 LL | impl<T> Foo for T {}
-   | ----------------- first implementation here
+   | ----------------- positive implementation here
 LL | impl !Foo for u8 {}
-   | ^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+   | ^^^^^^^^^^^^^^^^ negative implementation here
 
-error[E0119]: conflicting implementations of trait `Bar` for type `u8`:
+error[E0748]: found both positive and negative implementation of trait `Bar` for type `u8`:
   --> $DIR/specialization-polarity.rs:14:1
    |
 LL | impl<T> !Bar for T {}
-   | ------------------ first implementation here
+   | ------------------ negative implementation here
 LL | impl Bar for u8 {}
-   | ^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+   | ^^^^^^^^^^^^^^^ positive implementation here
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
index 2ebf0bdcbe9..c7009430eae 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -6,8 +6,8 @@ trait MyTrait {
     fn foo();
 }
 impl<T> MyTrait for T {
-    default fn foo() { }
+    default fn foo() {}
 }
-impl !MyTrait for u32 { } //~ ERROR conflicting implementations
+impl !MyTrait for u32 {} //~ ERROR E0748
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
index 83421b4d7a1..21fd08251d4 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -1,12 +1,12 @@
-error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive-item.rs:11:1
    |
 LL | impl<T> MyTrait for T {
-   | --------------------- first implementation here
+   | --------------------- positive implementation here
 ...
-LL | impl !MyTrait for u32 { }
-   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+LL | impl !MyTrait for u32 {}
+   | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
index 7ab01612295..25301c696e1 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -2,13 +2,13 @@
 #![feature(optin_builtin_traits)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
-trait MyTrait { }
-impl<T> MyTrait for T { }
-impl !MyTrait for u32 { } //~ ERROR conflicting implementations
+trait MyTrait {}
+impl<T> MyTrait for T {}
+impl !MyTrait for u32 {} //~ ERROR E0748
 
 // The second impl specializes the first, no error.
-trait MyTrait2 { }
-impl<T> MyTrait2 for T { }
-impl MyTrait2 for u32 { }
+trait MyTrait2 {}
+impl<T> MyTrait2 for T {}
+impl MyTrait2 for u32 {}
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
index a542e88673e..0e7426c8260 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive.rs:7:1
    |
-LL | impl<T> MyTrait for T { }
-   | --------------------- first implementation here
-LL | impl !MyTrait for u32 { }
-   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+LL | impl<T> MyTrait for T {}
+   | --------------------- positive implementation here
+LL | impl !MyTrait for u32 {}
+   | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
index 5c3e7fe3d01..d9c498fca66 100644
--- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
@@ -4,13 +4,13 @@ use std::pin::Pin;
 
 struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
 
-impl<'a> Clone for &'a mut MyType<'a> { //~ ERROR conflicting implementations
+impl<'a> Clone for &'a mut MyType<'a> {
+    //~^ ERROR E0748
     fn clone(&self) -> &'a mut MyType<'a> {
         self.0.replace(None).unwrap()
     }
 }
 
-
 fn main() {
     let mut unpinned = MyType(Cell::new(None), PhantomPinned);
     let bad_addr = &unpinned as *const MyType<'_> as usize;
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
index 1655d806fb4..f3305722cf2 100644
--- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
@@ -1,13 +1,11 @@
-error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `&mut MyType<'_>`:
+error[E0748]: found both positive and negative implementation of trait `std::clone::Clone` for type `&mut MyType<'_>`:
   --> $DIR/pin-unsound-issue-66544-clone.rs:7:1
    |
 LL | impl<'a> Clone for &'a mut MyType<'a> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here
    |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> std::clone::Clone for &mut T
-             where T: ?Sized;
+   = note: negative implementation in crate `core`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
index a34b8d635ab..cc27c301ffa 100644
--- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
@@ -9,13 +9,13 @@ use std::pin::Pin;
 
 struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
 
-impl<'a> DerefMut for &'a MyType<'a> { //~ ERROR conflicting implementations
+impl<'a> DerefMut for &'a MyType<'a> {
+    //~^ ERROR E0748
     fn deref_mut(&mut self) -> &mut MyType<'a> {
         self.0.replace(None).unwrap()
     }
 }
 
-
 fn main() {
     let mut unpinned = MyType(Cell::new(None), PhantomPinned);
     let bad_addr = &unpinned as *const MyType<'_> as usize;
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
index 80c9682a010..4e71c246824 100644
--- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
@@ -1,13 +1,11 @@
-error[E0119]: conflicting implementations of trait `std::ops::DerefMut` for type `&MyType<'_>`:
+error[E0748]: found both positive and negative implementation of trait `std::ops::DerefMut` for type `&MyType<'_>`:
   --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1
    |
 LL | impl<'a> DerefMut for &'a MyType<'a> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here
    |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> std::ops::DerefMut for &T
-             where T: ?Sized;
+   = note: negative implementation in crate `core`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
index 20267cf3aba..8a8ee70370f 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -1,9 +1,9 @@
 #![feature(specialization)]
 #![feature(optin_builtin_traits)]
 
-trait MyTrait { }
+trait MyTrait {}
 
-impl<T> !MyTrait for T { }
-impl MyTrait for u32 { } //~ ERROR conflicting implementations
+impl<T> !MyTrait for T {}
+impl MyTrait for u32 {} //~ ERROR E0748
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
index 6e41759d2a2..ab371945a7e 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/positive-specializes-negative.rs:7:1
    |
-LL | impl<T> !MyTrait for T { }
-   | ---------------------- first implementation here
-LL | impl MyTrait for u32 { }
-   | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+LL | impl<T> !MyTrait for T {}
+   | ---------------------- negative implementation here
+LL | impl MyTrait for u32 {}
+   | ^^^^^^^^^^^^^^^^^^^^ positive implementation here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0748`.