summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/negative-impls
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/traits/negative-impls
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/traits/negative-impls')
-rw-r--r--tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs7
-rw-r--r--tests/ui/traits/negative-impls/eager-mono.rs12
-rw-r--r--tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs53
-rw-r--r--tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr52
-rw-r--r--tests/ui/traits/negative-impls/feature-gate-negative_impls.rs3
-rw-r--r--tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr12
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-error.rs68
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-error.stderr127
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs21
-rw-r--r--tests/ui/traits/negative-impls/negative-default-impls.rs11
-rw-r--r--tests/ui/traits/negative-impls/negative-default-impls.stderr19
-rw-r--r--tests/ui/traits/negative-impls/negative-impls-basic.rs17
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-negative.rs13
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-negative.stderr12
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive-item.rs13
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr22
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive.rs14
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive.stderr21
-rw-r--r--tests/ui/traits/negative-impls/no-items.rs11
-rw-r--r--tests/ui/traits/negative-impls/no-items.stderr9
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs26
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr11
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs33
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr11
-rw-r--r--tests/ui/traits/negative-impls/positive-specializes-negative.rs9
-rw-r--r--tests/ui/traits/negative-impls/positive-specializes-negative.stderr21
-rw-r--r--tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs24
27 files changed, 652 insertions, 0 deletions
diff --git a/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs
new file mode 100644
index 000000000..0e17f0890
--- /dev/null
+++ b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs
@@ -0,0 +1,7 @@
+#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
+
+pub trait ForeignTrait {}
+
+impl ForeignTrait for u32 {}
+impl !ForeignTrait for String {}
diff --git a/tests/ui/traits/negative-impls/eager-mono.rs b/tests/ui/traits/negative-impls/eager-mono.rs
new file mode 100644
index 000000000..ce770376c
--- /dev/null
+++ b/tests/ui/traits/negative-impls/eager-mono.rs
@@ -0,0 +1,12 @@
+// build-pass
+// compile-flags:-C link-dead-code=y
+
+#![feature(negative_impls)]
+
+trait Foo {
+ fn foo() {}
+}
+
+impl !Foo for () {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
new file mode 100644
index 000000000..17ddaa312
--- /dev/null
+++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
@@ -0,0 +1,53 @@
+// This tests issue #79683: note in the error message that the trait is
+// explicitly unimplemented instead of suggesting to implement it.
+
+#![feature(negative_impls)]
+
+struct Qux;
+//~^ NOTE method `clone` not found for this
+//~^^ NOTE method `foo` not found for this
+
+impl !Clone for Qux {}
+
+trait Bar {
+ fn bar(&self);
+}
+
+impl !Bar for u32 {}
+
+trait Foo {
+ fn foo(&self);
+}
+//~^^^ NOTE `Foo` defines an item `foo`, perhaps you need to implement it
+
+trait FooBar {
+ fn foo(&self);
+}
+
+impl !Foo for Qux {}
+
+impl !FooBar for Qux {}
+
+impl !FooBar for u32 {}
+
+fn main() {
+ Qux.clone();
+ //~^ ERROR no method named `clone` found for struct `Qux`
+ //~| NOTE method not found in `Qux`
+ //~| NOTE `Clone` defines an item `clone`, but is explicitly unimplemented
+
+ 0_u32.bar();
+ //~^ ERROR no method named `bar` found for type `u32`
+ //~| NOTE method not found in `u32`
+ //~| NOTE `Bar` defines an item `bar`, but is explicitly unimplemented
+
+ Qux.foo();
+ //~^ ERROR no method named `foo` found for struct `Qux`
+ //~| NOTE method not found in `Qux`
+ //~| NOTE the following traits define an item `foo`, but are explicitly unimplemented
+
+ 0_u32.foo();
+ //~^ ERROR no method named `foo` found for type `u32`
+ //~| NOTE method not found in `u32`
+ //~| NOTE `FooBar` defines an item `foo`, but is explicitly unimplemented
+}
diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
new file mode 100644
index 000000000..b29442d7b
--- /dev/null
+++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
@@ -0,0 +1,52 @@
+error[E0599]: no method named `clone` found for struct `Qux` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:34:9
+ |
+LL | struct Qux;
+ | ---------- method `clone` not found for this struct
+...
+LL | Qux.clone();
+ | ^^^^^ method not found in `Qux`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the trait `Clone` defines an item `clone`, but is explicitly unimplemented
+
+error[E0599]: no method named `bar` found for type `u32` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:39:11
+ |
+LL | 0_u32.bar();
+ | ^^^ method not found in `u32`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the trait `Bar` defines an item `bar`, but is explicitly unimplemented
+
+error[E0599]: no method named `foo` found for struct `Qux` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:44:9
+ |
+LL | struct Qux;
+ | ---------- method `foo` not found for this struct
+...
+LL | Qux.foo();
+ | ^^^ method not found in `Qux`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following traits define an item `foo`, but are explicitly unimplemented:
+ Foo
+ FooBar
+
+error[E0599]: no method named `foo` found for type `u32` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:49:11
+ |
+LL | 0_u32.foo();
+ | ^^^ method not found in `u32`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Foo` defines an item `foo`, perhaps you need to implement it
+ --> $DIR/explicitly-unimplemented-error-message.rs:18:1
+ |
+LL | trait Foo {
+ | ^^^^^^^^^
+ = note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
new file mode 100644
index 000000000..683fd6db6
--- /dev/null
+++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
@@ -0,0 +1,3 @@
+trait MyTrait {}
+impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
new file mode 100644
index 000000000..b253fbd0d
--- /dev/null
+++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
@@ -0,0 +1,12 @@
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
+ --> $DIR/feature-gate-negative_impls.rs:2:6
+ |
+LL | impl !MyTrait for u32 {}
+ | ^^^^^^^^
+ |
+ = note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
+ = help: add `#![feature(negative_impls)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.rs b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs
new file mode 100644
index 000000000..4bdad5dc5
--- /dev/null
+++ b/tests/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(negative_impls)]
+
+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/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
new file mode 100644
index 000000000..ce690b749
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -0,0 +1,127 @@
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:23:11
+ |
+LL | Outer(TestType);
+ | ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `dummy::TestType`
+note: required by a bound in `Outer`
+ --> $DIR/negated-auto-traits-error.rs:10:17
+ |
+LL | struct Outer<T: Send>(T);
+ | ^^^^ required by this bound in `Outer`
+
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:23:5
+ |
+LL | Outer(TestType);
+ | ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+ |
+ = help: the trait `Send` is not implemented for `dummy::TestType`
+note: required by a bound in `Outer`
+ --> $DIR/negated-auto-traits-error.rs:10:17
+ |
+LL | struct Outer<T: Send>(T);
+ | ^^^^ required by this bound in `Outer`
+
+error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:32:13
+ |
+LL | is_send(TestType);
+ | ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `dummy1b::TestType`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:40:13
+ |
+LL | is_send((8, TestType));
+ | ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
+ = note: required because it appears within the type `({integer}, TestType)`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `dummy2::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:48:13
+ |
+LL | is_send(Box::new(TestType));
+ | ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique<dummy2::TestType>`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied
+ = note: required for `Unique<dummy2::TestType>` to implement `Send`
+ = note: required because it appears within the type `Box<TestType>`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider borrowing here
+ |
+LL | is_send(&Box::new(TestType));
+ | +
+
+error[E0277]: `dummy3::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:56:13
+ |
+LL | is_send(Box::new(Outer2(TestType)));
+ | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
+note: required because it appears within the type `Outer2<TestType>`
+ --> $DIR/negated-auto-traits-error.rs:12:8
+ |
+LL | struct Outer2<T>(T);
+ | ^^^^^^
+ = note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send`
+ = note: required because it appears within the type `Box<Outer2<TestType>>`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `main::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:66:13
+ |
+LL | is_sync(Outer2(TestType));
+ | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `main::TestType`
+note: required for `Outer2<main::TestType>` to implement `Sync`
+ --> $DIR/negated-auto-traits-error.rs:14:22
+ |
+LL | unsafe impl<T: Send> Sync for Outer2<T> {}
+ | ---- ^^^^ ^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `is_sync`
+ --> $DIR/negated-auto-traits-error.rs:17:15
+ |
+LL | fn is_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `is_sync`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
new file mode 100644
index 000000000..a1042f831
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(unused_variables)]
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+pub struct WaitToken;
+impl !Send for WaitToken {}
+
+pub struct Test<T>(#[allow(unused_tuple_struct_fields)] 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/tests/ui/traits/negative-impls/negative-default-impls.rs b/tests/ui/traits/negative-impls/negative-default-impls.rs
new file mode 100644
index 000000000..c68bca432
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-default-impls.rs
@@ -0,0 +1,11 @@
+#![feature(negative_impls)]
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait MyTrait {
+ type Foo;
+}
+
+default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-default-impls.stderr b/tests/ui/traits/negative-impls/negative-default-impls.stderr
new file mode 100644
index 000000000..7b54cf542
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-default-impls.stderr
@@ -0,0 +1,19 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-default-impls.rs:2:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0750]: negative impls cannot be default impls
+ --> $DIR/negative-default-impls.rs:9:1
+ |
+LL | default impl !MyTrait for u32 {}
+ | ^^^^^^^ ^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0750`.
diff --git a/tests/ui/traits/negative-impls/negative-impls-basic.rs b/tests/ui/traits/negative-impls/negative-impls-basic.rs
new file mode 100644
index 000000000..474e03817
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-impls-basic.rs
@@ -0,0 +1,17 @@
+// A simple test that we are able to create negative impls, when the
+// feature gate is given.
+//
+// run-pass
+
+#![feature(negative_impls)]
+#![allow(dead_code)]
+
+struct TestType;
+
+trait TestTrait {
+ fn dummy(&self) {}
+}
+
+impl !TestTrait for TestType {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs
new file mode 100644
index 000000000..35297ab12
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs
@@ -0,0 +1,13 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+// Test a negative impl that "specializes" another negative impl.
+//
+// run-pass
+
+trait MyTrait {}
+
+impl<T> !MyTrait for T {}
+impl !MyTrait for u32 {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.stderr b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr
new file mode 100644
index 000000000..751e29c3b
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-specializes-negative.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
new file mode 100644
index 000000000..4281eedaf
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -0,0 +1,13 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+// 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 E0751
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
new file mode 100644
index 000000000..1cfa49b20
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -0,0 +1,22 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-specializes-positive-item.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: 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 {
+ | --------------------- positive implementation here
+...
+LL | impl !MyTrait for u32 {}
+ | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.rs b/tests/ui/traits/negative-impls/negative-specializes-positive.rs
new file mode 100644
index 000000000..0e227691e
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -0,0 +1,14 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+// Negative impl for u32 cannot "specialize" the base impl.
+trait MyTrait {}
+impl<T> MyTrait for T {}
+impl !MyTrait for u32 {} //~ ERROR E0751
+
+// The second impl specializes the first, no error.
+trait MyTrait2 {}
+impl<T> MyTrait2 for T {}
+impl MyTrait2 for u32 {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
new file mode 100644
index 000000000..9f9e28678
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-specializes-positive.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: 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 {}
+ | --------------------- positive implementation here
+LL | impl !MyTrait for u32 {}
+ | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/no-items.rs b/tests/ui/traits/negative-impls/no-items.rs
new file mode 100644
index 000000000..5fc6be9b3
--- /dev/null
+++ b/tests/ui/traits/negative-impls/no-items.rs
@@ -0,0 +1,11 @@
+#![feature(negative_impls)]
+
+trait MyTrait {
+ type Foo;
+}
+
+impl !MyTrait for u32 {
+ type Foo = i32; //~ ERROR negative impls cannot have any items
+}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr
new file mode 100644
index 000000000..67b94bba1
--- /dev/null
+++ b/tests/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/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
new file mode 100644
index 000000000..a5b856465
--- /dev/null
+++ b/tests/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 E0751
+ fn clone(&self) -> &'a mut MyType<'a> {
+ self.0.take().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/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
new file mode 100644
index 000000000..a87acb1fb
--- /dev/null
+++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
@@ -0,0 +1,11 @@
+error[E0751]: found both positive and negative implementation of trait `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: negative implementation in crate `core`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
new file mode 100644
index 000000000..606cc65a8
--- /dev/null
+++ b/tests/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 E0751
+ fn deref_mut(&mut self) -> &mut MyType<'a> {
+ self.0.take().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/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
new file mode 100644
index 000000000..9185e8f84
--- /dev/null
+++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
@@ -0,0 +1,11 @@
+error[E0751]: found both positive and negative implementation of trait `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: negative implementation in crate `core`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.rs b/tests/ui/traits/negative-impls/positive-specializes-negative.rs
new file mode 100644
index 000000000..a06b35765
--- /dev/null
+++ b/tests/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -0,0 +1,9 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+trait MyTrait {}
+
+impl<T> !MyTrait for T {}
+impl MyTrait for u32 {} //~ ERROR E0751
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
new file mode 100644
index 000000000..545f94143
--- /dev/null
+++ b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/positive-specializes-negative.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: 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 {}
+ | ---------------------- negative implementation here
+LL | impl MyTrait for u32 {}
+ | ^^^^^^^^^^^^^^^^^^^^ positive implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
new file mode 100644
index 000000000..c1f96ab8c
--- /dev/null
+++ b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
+
+// 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 {}
+
+fn main() {}