-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #68004 - nikomatsakis:negative-impls, r=varkor
permit negative impls for non-auto traits This is a prototype impl that extends `impl !Trait` beyond auto traits. It is not integrated with coherence or anything else, and hence only serves to prevent downstream impls (but not to allow downstream crates to rely on the absence of such impls for coherence purposes). Fixes #66544 TODO: - [x] need a test that you can't rely on negative impls for coherence purposes - [x] test that negative impls cannot specialize positive ones - [x] test that positive impls cannot specialize negative ones - [x] extend negative impl to `Clone` in order to fully fix #66544 - [x] and maybe make `CoerceUnsized` unsafe? -- that problem is now split out into #68015 - [x] introduce feature flag and prepare a write-up - [x] improve diagnostics?
- Loading branch information
Showing
133 changed files
with
869 additions
and
351 deletions.
There are no files selected for viewing
57 changes: 57 additions & 0 deletions
57
src/doc/unstable-book/src/language-features/negative-impls.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# `negative_impls` | ||
|
||
The tracking issue for this feature is [#68318]. | ||
|
||
[#68318]: https://github.com/rust-lang/rust/issues/68318 | ||
|
||
---- | ||
|
||
With the feature gate `negative_impls`, you can write negative impls as well as positive ones: | ||
|
||
```rust | ||
#![feature(negative_impls)] | ||
trait DerefMut { } | ||
impl<T: ?Sized> !DerefMut for &T { } | ||
``` | ||
|
||
Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below. | ||
|
||
Negative impls have the following characteristics: | ||
|
||
* They do not have any items. | ||
* They must obey the orphan rules as if they were a positive impl. | ||
* They cannot "overlap" with any positive impls. | ||
|
||
## Semver interaction | ||
|
||
It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types. | ||
|
||
## Orphan and overlap rules | ||
|
||
Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth. | ||
|
||
Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.) | ||
|
||
## Interaction with auto traits | ||
|
||
Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an | ||
auto-trait serves two purposes: | ||
|
||
* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`; | ||
* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated. | ||
|
||
Note that, at present, there is no way to indicate that a given type | ||
does not implement an auto trait *but that it may do so in the | ||
future*. For ordinary types, this is done by simply not declaring any | ||
impl at all, but that is not an option for auto traits. A workaround | ||
is that one could embed a marker type as one of the fields, where the | ||
marker type is `!AutoTrait`. | ||
|
||
## Immediate uses | ||
|
||
Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544). | ||
|
||
This serves two purposes: | ||
|
||
* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. | ||
* It prevents downstream crates from creating such impls. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Negative impls are not allowed to have any items. Negative impls | ||
declare that a trait is **not** implemented (and never will be) and | ||
hence there is no need to specify the values for trait methods or | ||
other items. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Negative impls cannot be default impls. A default impl supplies | ||
default values for the items within to be used by other impls, whereas | ||
a negative impl declares that there are no other impls. These don't | ||
make sense to combine. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
There are both a positive and negative trait implementation for the same type. | ||
|
||
Erroneous code example: | ||
|
||
```compile_fail,E0748 | ||
trait MyTrait {} | ||
impl MyTrait for i32 { } | ||
impl !MyTrait for i32 { } | ||
``` | ||
|
||
Negative implementations are a promise that the trait will never be | ||
implemented for the given types. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.