about summary refs log tree commit diff
path: root/src/test/ui/traits/negative-impls
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/traits/negative-impls')
-rw-r--r--src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs6
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-error.rs68
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr93
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs21
-rw-r--r--src/test/ui/traits/negative-impls/negative-default-impls.rs10
-rw-r--r--src/test/ui/traits/negative-impls/negative-default-impls.stderr9
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs13
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr12
-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.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/no-items.rs11
-rw-r--r--src/test/ui/traits/negative-impls/no-items.stderr9
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs26
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr13
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs33
-rw-r--r--src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr13
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.rs9
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs21
-rw-r--r--src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs14
21 files changed, 428 insertions, 0 deletions
diff --git a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs
new file mode 100644
index 00000000000..1790b24be33
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs
@@ -0,0 +1,6 @@
+#![feature(optin_builtin_traits)]
+
+pub trait ForeignTrait { }
+
+impl ForeignTrait for u32 { }
+impl !ForeignTrait for String {}
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs
new file mode 100644
index 00000000000..fb9a3a99748
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs
@@ -0,0 +1,68 @@
+// The dummy functions are used to avoid adding new cfail files.
+// What happens is that the compiler attempts to squash duplicates and some
+// errors are not reported. This way, we make sure that, for each function, different
+// typeck phases are involved and all errors are reported.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn dummy() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    Outer(TestType);
+    //~^ ERROR `dummy::TestType` cannot be sent between threads safely
+    //~| ERROR `dummy::TestType` cannot be sent between threads safely
+}
+
+fn dummy1b() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(TestType);
+    //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely
+}
+
+fn dummy1c() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send((8, TestType));
+    //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely
+}
+
+fn dummy2() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(Box::new(TestType));
+    //~^ ERROR `dummy2::TestType` cannot be sent between threads safely
+}
+
+fn dummy3() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(Box::new(Outer2(TestType)));
+    //~^ ERROR `dummy3::TestType` cannot be sent between threads safely
+}
+
+fn main() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    // This will complain about a missing Send impl because `Sync` is implement *just*
+    // for T that are `Send`. Look at #20366 and #19950
+    is_sync(Outer2(TestType));
+    //~^ ERROR `main::TestType` cannot be sent between threads safely
+}
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
new file mode 100644
index 00000000000..69a91b09e3e
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -0,0 +1,93 @@
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:23:11
+   |
+LL | struct Outer<T: Send>(T);
+   | ------------------------- required by `Outer`
+...
+LL |     Outer(TestType);
+   |           ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
+
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:23:5
+   |
+LL | struct Outer<T: Send>(T);
+   | ------------------------- required by `Outer`
+...
+LL |     Outer(TestType);
+   |     ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
+
+error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:32:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(TestType);
+   |             ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType`
+
+error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:40:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send((8, TestType));
+   |             ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |
+   = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType`
+   = note: required because it appears within the type `({integer}, dummy1c::TestType)`
+
+error[E0277]: `dummy2::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:48:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(Box::new(TestType));
+   |             ^^^^^^^^^^^^^^^^^^
+   |             |
+   |             expected an implementor of trait `std::marker::Send`
+   |             help: consider borrowing here: `&Box::new(TestType)`
+   |
+   = note: the trait bound `dummy2::TestType: std::marker::Send` is not satisfied
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dummy2::TestType>`
+   = note: required because it appears within the type `std::boxed::Box<dummy2::TestType>`
+
+error[E0277]: `dummy3::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:56:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(Box::new(Outer2(TestType)));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |
+   = help: within `Outer2<dummy3::TestType>`, the trait `std::marker::Send` is not implemented for `dummy3::TestType`
+   = note: required because it appears within the type `Outer2<dummy3::TestType>`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<Outer2<dummy3::TestType>>`
+   = note: required because it appears within the type `std::boxed::Box<Outer2<dummy3::TestType>>`
+
+error[E0277]: `main::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:66:13
+   |
+LL | fn is_sync<T: Sync>(_: T) {}
+   |    -------    ---- required by this bound in `is_sync`
+...
+LL |     is_sync(Outer2(TestType));
+   |             ^^^^^^^^^^^^^^^^
+   |             |
+   |             expected an implementor of trait `std::marker::Sync`
+   |             help: consider borrowing here: `&Outer2(TestType)`
+   |
+   = note: the trait bound `main::TestType: std::marker::Sync` is not satisfied
+   = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2<main::TestType>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs
new file mode 100644
index 00000000000..8664b6a6a6e
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(unused_variables)]
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+pub struct WaitToken;
+impl !Send for WaitToken {}
+
+pub struct Test<T>(T);
+unsafe impl<T: 'static> Send for Test<T> {}
+
+pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
+
+fn main() {
+    let wt = Test(WaitToken);
+    spawn(move || {
+        let x = wt;
+        println!("Hello, World!");
+    });
+}
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs
new file mode 100644
index 00000000000..b23ac87f899
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs
@@ -0,0 +1,10 @@
+#![feature(optin_builtin_traits)]
+#![feature(specialization)]
+
+trait MyTrait {
+    type Foo;
+}
+
+default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls
+
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
new file mode 100644
index 00000000000..d2423d01a9a
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
@@ -0,0 +1,9 @@
+error[E0750]: negative impls cannot be default impls
+  --> $DIR/negative-default-impls.rs:8:14
+   |
+LL | default impl !MyTrait for u32 {}
+   | ^^^^^^^      ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0750`.
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
new file mode 100644
index 00000000000..2ebf0bdcbe9
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -0,0 +1,13 @@
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+// Negative impl for u32 cannot "specialize" the base impl.
+trait MyTrait {
+    fn foo();
+}
+impl<T> MyTrait for T {
+    default fn foo() { }
+}
+impl !MyTrait for u32 { } //~ ERROR conflicting implementations
+
+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
new file mode 100644
index 00000000000..83421b4d7a1
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+  --> $DIR/negative-specializes-positive-item.rs:11:1
+   |
+LL | impl<T> MyTrait for T {
+   | --------------------- first implementation here
+...
+LL | impl !MyTrait for u32 { }
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
new file mode 100644
index 00000000000..7ab01612295
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -0,0 +1,14 @@
+#![feature(specialization)]
+#![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
+
+// The second impl specializes the first, no error.
+trait MyTrait2 { }
+impl<T> MyTrait2 for T { }
+impl MyTrait2 for u32 { }
+
+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
new file mode 100644
index 00000000000..a542e88673e
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations 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`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/no-items.rs b/src/test/ui/traits/negative-impls/no-items.rs
new file mode 100644
index 00000000000..5bfbf9653ab
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/no-items.rs
@@ -0,0 +1,11 @@
+#![feature(optin_builtin_traits)]
+
+trait MyTrait {
+    type Foo;
+}
+
+impl !MyTrait for u32 {
+    type Foo = i32; //~ ERROR negative impls cannot have any items
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/no-items.stderr b/src/test/ui/traits/negative-impls/no-items.stderr
new file mode 100644
index 00000000000..67b94bba121
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/no-items.stderr
@@ -0,0 +1,9 @@
+error[E0749]: negative impls cannot have any items
+  --> $DIR/no-items.rs:8:5
+   |
+LL |     type Foo = i32;
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0749`.
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
new file mode 100644
index 00000000000..5c3e7fe3d01
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
@@ -0,0 +1,26 @@
+use std::cell::Cell;
+use std::marker::PhantomPinned;
+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
+    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;
+    let mut p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned));
+
+    // p_mut1 is okay: it does not point to the bad_addr
+    let p_mut1: Pin<&mut MyType<'_>> = p.as_mut();
+    assert_ne!(bad_addr, &*p_mut1 as *const _ as usize);
+
+    // but p_mut2 does point to bad_addr! this is unsound
+    let p_mut2: Pin<&mut MyType<'_>> = p_mut1.clone();
+    assert_eq!(bad_addr, &*p_mut2 as *const _ 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
new file mode 100644
index 00000000000..1655d806fb4
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations 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> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::clone::Clone for &mut T
+             where T: ?Sized;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
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
new file mode 100644
index 00000000000..a34b8d635ab
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
@@ -0,0 +1,33 @@
+// Demonstrate that "rogue" `DerefMut` impls for `&T` are not allowed.
+//
+// https://github.com/rust-lang/rust/issues/66544
+
+use std::cell::Cell;
+use std::marker::PhantomPinned;
+use std::ops::DerefMut;
+use std::pin::Pin;
+
+struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
+
+impl<'a> DerefMut for &'a MyType<'a> { //~ ERROR conflicting implementations
+    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;
+    let p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned));
+
+    // p_ref is okay: it does not point to the bad_addr
+    let mut p_ref: Pin<&MyType<'_>> = p.as_ref();
+    assert_ne!(bad_addr, &*p_ref as *const _ as usize);
+
+    // but p_mut does point to bad_addr! this is unsound
+    let p_mut: Pin<&mut MyType<'_>> = p_ref.as_mut();
+    assert_eq!(bad_addr, &*p_mut as *const _ as usize);
+
+    println!("oh no!");
+}
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
new file mode 100644
index 00000000000..80c9682a010
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations 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> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::ops::DerefMut for &T
+             where T: ?Sized;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
new file mode 100644
index 00000000000..20267cf3aba
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -0,0 +1,9 @@
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+trait MyTrait { }
+
+impl<T> !MyTrait for T { }
+impl MyTrait for u32 { } //~ ERROR conflicting implementations
+
+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
new file mode 100644
index 00000000000..6e41759d2a2
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations 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`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
new file mode 100644
index 00000000000..b823c0f7864
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
@@ -0,0 +1,21 @@
+#![feature(optin_builtin_traits)]
+
+// aux-build: foreign_trait.rs
+
+// Test that we cannot implement `LocalTrait` for `String`,
+// even though there is a `String: !ForeignTrait` impl.
+//
+// This may not be the behavior we want long term, but it's the
+// current semantics that we implemented so as to land `!Foo` impls
+// quickly. See internals thread:
+//
+// https://internals.rust-lang.org/t/foo/11587/
+
+extern crate foreign_trait;
+use foreign_trait::ForeignTrait;
+
+trait LocalTrait { }
+impl<T: ForeignTrait> LocalTrait for T { }
+impl LocalTrait for String { } //~ ERROR conflicting implementations
+
+fn main() { }
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr
new file mode 100644
index 00000000000..7cce45d2c8f
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `LocalTrait` for type `std::string::String`:
+  --> $DIR/rely-on-negative-impl-in-coherence.rs:19:1
+   |
+LL | impl<T: ForeignTrait> LocalTrait for T { }
+   | -------------------------------------- first implementation here
+LL | impl LocalTrait for String { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs
new file mode 100644
index 00000000000..6a2e99f8147
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+#![feature(optin_builtin_traits)]
+#![allow(dead_code)]
+
+struct TestType;
+
+trait TestTrait {
+    fn dummy(&self) {}
+}
+
+impl !TestTrait for TestType {}
+
+fn main() {}