From e8a05e201ee6cea12fe05e4271e91fd40c2fb235 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 8 Jan 2020 06:39:38 -0500 Subject: permit negative impls for non-auto traits --- src/test/ui/error-codes/E0192.rs | 12 --- src/test/ui/error-codes/E0192.stderr | 11 --- .../ui/specialization/defaultimpl/validation.rs | 3 +- .../specialization/defaultimpl/validation.stderr | 18 +++-- src/test/ui/syntax-trait-polarity.rs | 2 - src/test/ui/syntax-trait-polarity.stderr | 25 +----- .../negative-impls/auxiliary/foreign_trait.rs | 6 ++ .../negative-impls/negated-auto-traits-error.rs | 68 ++++++++++++++++ .../negated-auto-traits-error.stderr | 93 ++++++++++++++++++++++ .../negative-impls/negated-auto-traits-rpass.rs | 21 +++++ .../negative-impls/negative-default-impls.rs | 10 +++ .../negative-impls/negative-default-impls.stderr | 9 +++ .../negative-specializes-positive-item.rs | 13 +++ .../negative-specializes-positive-item.stderr | 12 +++ .../negative-specializes-positive.rs | 14 ++++ .../negative-specializes-positive.stderr | 11 +++ src/test/ui/traits/negative-impls/no-items.rs | 11 +++ src/test/ui/traits/negative-impls/no-items.stderr | 9 +++ .../pin-unsound-issue-66544-clone.rs | 26 ++++++ .../pin-unsound-issue-66544-clone.stderr | 13 +++ .../pin-unsound-issue-66544-derefmut.rs | 33 ++++++++ .../pin-unsound-issue-66544-derefmut.stderr | 13 +++ .../positive-specializes-negative.rs | 9 +++ .../positive-specializes-negative.stderr | 11 +++ .../rely-on-negative-impl-in-coherence.rs | 21 +++++ .../rely-on-negative-impl-in-coherence.stderr | 11 +++ .../typeck-negative-impls-builtin.rs | 14 ++++ src/test/ui/traits/traits-negative-impls-rpass.rs | 21 ----- src/test/ui/traits/traits-negative-impls.rs | 68 ---------------- src/test/ui/traits/traits-negative-impls.stderr | 93 ---------------------- .../ui/typeck/typeck-negative-impls-builtin.rs | 12 --- .../ui/typeck/typeck-negative-impls-builtin.stderr | 11 --- 32 files changed, 445 insertions(+), 259 deletions(-) delete mode 100644 src/test/ui/error-codes/E0192.rs delete mode 100644 src/test/ui/error-codes/E0192.stderr create mode 100644 src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs create mode 100644 src/test/ui/traits/negative-impls/negated-auto-traits-error.rs create mode 100644 src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr create mode 100644 src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs create mode 100644 src/test/ui/traits/negative-impls/negative-default-impls.rs create mode 100644 src/test/ui/traits/negative-impls/negative-default-impls.stderr create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive.rs create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive.stderr create mode 100644 src/test/ui/traits/negative-impls/no-items.rs create mode 100644 src/test/ui/traits/negative-impls/no-items.stderr create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr create mode 100644 src/test/ui/traits/negative-impls/positive-specializes-negative.rs create mode 100644 src/test/ui/traits/negative-impls/positive-specializes-negative.stderr create mode 100644 src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs create mode 100644 src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr create mode 100644 src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs delete mode 100644 src/test/ui/traits/traits-negative-impls-rpass.rs delete mode 100644 src/test/ui/traits/traits-negative-impls.rs delete mode 100644 src/test/ui/traits/traits-negative-impls.stderr delete mode 100644 src/test/ui/typeck/typeck-negative-impls-builtin.rs delete mode 100644 src/test/ui/typeck/typeck-negative-impls-builtin.stderr (limited to 'src/test/ui') diff --git a/src/test/ui/error-codes/E0192.rs b/src/test/ui/error-codes/E0192.rs deleted file mode 100644 index c52977e49b4..00000000000 --- a/src/test/ui/error-codes/E0192.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(optin_builtin_traits)] - -trait Trait { - type Bar; -} - -struct Foo; - -impl !Trait for Foo { } //~ ERROR E0192 - -fn main() { -} diff --git a/src/test/ui/error-codes/E0192.stderr b/src/test/ui/error-codes/E0192.stderr deleted file mode 100644 index da706dea167..00000000000 --- a/src/test/ui/error-codes/E0192.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0192]: invalid negative impl - --> $DIR/E0192.rs:9:6 - | -LL | impl !Trait for Foo { } - | ^^^^^^ - | - = note: negative impls are only allowed for auto traits, like `Send` and `Sync` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0192`. diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index 5b8a72104e3..ac8742c70c8 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -8,8 +8,9 @@ default impl S {} //~ ERROR inherent impls cannot be `default` default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default + //~^ ERROR negative impls cannot be default impls trait Tr {} -default impl !Tr for S {} //~ ERROR invalid negative impl +default impl !Tr for S {} //~ ERROR negative impls cannot be default impls fn main() {} diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index e03153f343b..9bf59bd4f63 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -24,14 +24,18 @@ LL | default impl !Send for Z {} | | | default because of this -error[E0192]: invalid negative impl - --> $DIR/validation.rs:13:14 +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:10:14 | -LL | default impl !Tr for S {} - | ^^^ +LL | default impl !Send for Z {} + | ^^^^^^^ ^ + +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:14:14 | - = note: negative impls are only allowed for auto traits, like `Send` and `Sync` +LL | default impl !Tr for S {} + | ^^^^^^^ ^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0192`. +For more information about this error, try `rustc --explain E0750`. diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs index bfbe6394c16..739a3c12dfb 100644 --- a/src/test/ui/syntax-trait-polarity.rs +++ b/src/test/ui/syntax-trait-polarity.rs @@ -12,7 +12,6 @@ trait TestTrait {} unsafe impl !Send for TestType {} //~^ ERROR negative impls cannot be unsafe impl !TestTrait for TestType {} -//~^ ERROR invalid negative impl struct TestType2(T); @@ -22,6 +21,5 @@ impl !TestType2 {} unsafe impl !Send for TestType2 {} //~^ ERROR negative impls cannot be unsafe impl !TestTrait for TestType2 {} -//~^ ERROR invalid negative impl fn main() {} diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr index f70d67ec7dc..1fd40fb6657 100644 --- a/src/test/ui/syntax-trait-polarity.stderr +++ b/src/test/ui/syntax-trait-polarity.stderr @@ -16,7 +16,7 @@ LL | unsafe impl !Send for TestType {} | unsafe because of this error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:19:10 + --> $DIR/syntax-trait-polarity.rs:18:10 | LL | impl !TestType2 {} | -^^^^^^^^^^^^ inherent impl for this type @@ -24,7 +24,7 @@ LL | impl !TestType2 {} | negative because of this error[E0198]: negative impls cannot be unsafe - --> $DIR/syntax-trait-polarity.rs:22:16 + --> $DIR/syntax-trait-polarity.rs:21:16 | LL | unsafe impl !Send for TestType2 {} | ------ -^^^^ @@ -32,23 +32,6 @@ LL | unsafe impl !Send for TestType2 {} | | negative because of this | unsafe because of this -error[E0192]: invalid negative impl - --> $DIR/syntax-trait-polarity.rs:14:6 - | -LL | impl !TestTrait for TestType {} - | ^^^^^^^^^^ - | - = note: negative impls are only allowed for auto traits, like `Send` and `Sync` - -error[E0192]: invalid negative impl - --> $DIR/syntax-trait-polarity.rs:24:9 - | -LL | impl !TestTrait for TestType2 {} - | ^^^^^^^^^^ - | - = note: negative impls are only allowed for auto traits, like `Send` and `Sync` - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0192, E0198. -For more information about an error, try `rustc --explain E0192`. +For more information about this error, try `rustc --explain E0198`. 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); + +struct Outer2(T); + +unsafe impl Sync for Outer2 {} + +fn is_send(_: T) {} +fn is_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); + | ------------------------- 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); + | ------------------------- 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) {} + | ------- ---- 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) {} + | ------- ---- 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) {} + | ------- ---- 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` + = note: required because it appears within the type `std::boxed::Box` + +error[E0277]: `dummy3::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:56:13 + | +LL | fn is_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`, the trait `std::marker::Send` is not implemented for `dummy3::TestType` + = note: required because it appears within the type `Outer2` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique>` + = note: required because it appears within the type `std::boxed::Box>` + +error[E0277]: `main::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:66:13 + | +LL | fn is_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` + +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); +unsafe impl Send for Test {} + +pub fn spawn(_: 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 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 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 MyTrait for T { } +impl !MyTrait for u32 { } //~ ERROR conflicting implementations + +// The second impl specializes the first, no error. +trait MyTrait2 { } +impl 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 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>>, 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 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>>, 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 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 !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 !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 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 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() {} diff --git a/src/test/ui/traits/traits-negative-impls-rpass.rs b/src/test/ui/traits/traits-negative-impls-rpass.rs deleted file mode 100644 index 8664b6a6a6e..00000000000 --- a/src/test/ui/traits/traits-negative-impls-rpass.rs +++ /dev/null @@ -1,21 +0,0 @@ -// run-pass -#![allow(unused_variables)] -#![feature(optin_builtin_traits)] - -use std::marker::Send; - -pub struct WaitToken; -impl !Send for WaitToken {} - -pub struct Test(T); -unsafe impl Send for Test {} - -pub fn spawn(_: 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/traits-negative-impls.rs b/src/test/ui/traits/traits-negative-impls.rs deleted file mode 100644 index fb9a3a99748..00000000000 --- a/src/test/ui/traits/traits-negative-impls.rs +++ /dev/null @@ -1,68 +0,0 @@ -// 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); - -struct Outer2(T); - -unsafe impl Sync for Outer2 {} - -fn is_send(_: T) {} -fn is_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/traits-negative-impls.stderr b/src/test/ui/traits/traits-negative-impls.stderr deleted file mode 100644 index 599bbfe2225..00000000000 --- a/src/test/ui/traits/traits-negative-impls.stderr +++ /dev/null @@ -1,93 +0,0 @@ -error[E0277]: `dummy::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:23:11 - | -LL | struct Outer(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/traits-negative-impls.rs:23:5 - | -LL | struct Outer(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/traits-negative-impls.rs:32:13 - | -LL | fn is_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/traits-negative-impls.rs:40:13 - | -LL | fn is_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/traits-negative-impls.rs:48:13 - | -LL | fn is_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` - = note: required because it appears within the type `std::boxed::Box` - -error[E0277]: `dummy3::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:56:13 - | -LL | fn is_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`, the trait `std::marker::Send` is not implemented for `dummy3::TestType` - = note: required because it appears within the type `Outer2` - = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique>` - = note: required because it appears within the type `std::boxed::Box>` - -error[E0277]: `main::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:66:13 - | -LL | fn is_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` - -error: aborting due to 7 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.rs b/src/test/ui/typeck/typeck-negative-impls-builtin.rs deleted file mode 100644 index fef98977cc4..00000000000 --- a/src/test/ui/typeck/typeck-negative-impls-builtin.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(optin_builtin_traits)] - -struct TestType; - -trait TestTrait { - fn dummy(&self) { } -} - -impl !TestTrait for TestType {} -//~^ ERROR invalid negative impl - -fn main() {} diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr b/src/test/ui/typeck/typeck-negative-impls-builtin.stderr deleted file mode 100644 index c90655086ac..00000000000 --- a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0192]: invalid negative impl - --> $DIR/typeck-negative-impls-builtin.rs:9:6 - | -LL | impl !TestTrait for TestType {} - | ^^^^^^^^^^ - | - = note: negative impls are only allowed for auto traits, like `Send` and `Sync` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0192`. -- cgit 1.4.1-3-g733a5