permit negative impls for non-auto traits

This commit is contained in:
Niko Matsakis 2020-01-08 06:39:38 -05:00
parent a17dd36084
commit e8a05e201e
35 changed files with 328 additions and 101 deletions

View file

@ -1,12 +0,0 @@
#![feature(optin_builtin_traits)]
trait Trait {
type Bar;
}
struct Foo;
impl !Trait for Foo { } //~ ERROR E0192
fn main() {
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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 !Send for Z {}
| ^^^^^^^ ^
error[E0750]: negative impls cannot be default impls
--> $DIR/validation.rs:14:14
|
LL | default impl !Tr for S {}
| ^^^
|
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
| ^^^^^^^ ^
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`.

View file

@ -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>(T);
@ -22,6 +21,5 @@ impl<T> !TestType2<T> {}
unsafe impl<T> !Send for TestType2<T> {}
//~^ ERROR negative impls cannot be unsafe
impl<T> !TestTrait for TestType2<T> {}
//~^ ERROR invalid negative impl
fn main() {}

View file

@ -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<T> !TestType2<T> {}
| -^^^^^^^^^^^^ inherent impl for this type
@ -24,7 +24,7 @@ LL | impl<T> !TestType2<T> {}
| 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<T> !Send for TestType2<T> {}
| ------ -^^^^
@ -32,23 +32,6 @@ LL | unsafe impl<T> !Send for TestType2<T> {}
| | 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: aborting due to 4 previous errors
error[E0192]: invalid negative impl
--> $DIR/syntax-trait-polarity.rs:24:9
|
LL | impl<T> !TestTrait for TestType2<T> {}
| ^^^^^^^^^^
|
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
error: aborting due to 6 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`.

View file

@ -0,0 +1,6 @@
#![feature(optin_builtin_traits)]
pub trait ForeignTrait { }
impl ForeignTrait for u32 { }
impl !ForeignTrait for String {}

View file

@ -1,5 +1,5 @@
error[E0277]: `dummy::TestType` cannot be sent between threads safely
--> $DIR/traits-negative-impls.rs:23:11
--> $DIR/negated-auto-traits-error.rs:23:11
|
LL | struct Outer<T: Send>(T);
| ------------------------- required by `Outer`
@ -10,7 +10,7 @@ LL | Outer(TestType);
= 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
--> $DIR/negated-auto-traits-error.rs:23:5
|
LL | struct Outer<T: Send>(T);
| ------------------------- required by `Outer`
@ -21,7 +21,7 @@ LL | Outer(TestType);
= 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
--> $DIR/negated-auto-traits-error.rs:32:13
|
LL | fn is_send<T: Send>(_: T) {}
| ------- ---- required by this bound in `is_send`
@ -32,7 +32,7 @@ LL | is_send(TestType);
= 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
--> $DIR/negated-auto-traits-error.rs:40:13
|
LL | fn is_send<T: Send>(_: T) {}
| ------- ---- required by this bound in `is_send`
@ -44,7 +44,7 @@ LL | is_send((8, 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
--> $DIR/negated-auto-traits-error.rs:48:13
|
LL | fn is_send<T: Send>(_: T) {}
| ------- ---- required by this bound in `is_send`
@ -60,7 +60,7 @@ LL | is_send(Box::new(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/traits-negative-impls.rs:56:13
--> $DIR/negated-auto-traits-error.rs:56:13
|
LL | fn is_send<T: Send>(_: T) {}
| ------- ---- required by this bound in `is_send`
@ -74,7 +74,7 @@ LL | is_send(Box::new(Outer2(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/traits-negative-impls.rs:66:13
--> $DIR/negated-auto-traits-error.rs:66:13
|
LL | fn is_sync<T: Sync>(_: T) {}
| ------- ---- required by this bound in `is_sync`

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() { }

View file

@ -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`.

View file

@ -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() { }

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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);
}

View file

@ -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`.

View file

@ -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!");
}

View file

@ -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`.

View file

@ -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() { }

View file

@ -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`.

View file

@ -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() { }

View file

@ -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`.

View file

@ -1,12 +1,14 @@
// run-pass
#![feature(optin_builtin_traits)]
#![allow(dead_code)]
struct TestType;
trait TestTrait {
fn dummy(&self) { }
fn dummy(&self) {}
}
impl !TestTrait for TestType {}
//~^ ERROR invalid negative impl
fn main() {}

View file

@ -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`.