-
Notifications
You must be signed in to change notification settings - Fork 550
add section on overlap checks #2042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 2 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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,72 @@ | ||
# Overlap checks | ||
|
||
As part of checking items (specifically: structs, enums, traits, unions), | ||
the compiler checks whether impl blocks overlap, for example because they define the same functions. | ||
This is an example an overlap check. | ||
The same overlap check is done when constructing a [specialization graph](./specialization.md). | ||
Here, trait implementations could overlap, for example because of a conflicting blanket implementation overlapping with some specific implementation. | ||
jdonszelmann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The overlap check always compares two impls. | ||
In the case of inherent impl blocks, this means that at least for small n, | ||
rustc quite literally compares each impl to each other impl block in an `n^2` loop | ||
jdonszelmann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(see `fn check_item` in coherence/inherent_impls_overlap.rs). | ||
|
||
Overlapping is sometimes partially allowed: | ||
1. for maker traits | ||
2. under [specialization](./specialization.md) | ||
|
||
but normally isn't. | ||
|
||
The overlap check has various modes (see [`OverlapMode`]). | ||
Importantly, there's the explicit negative impl check, and the implicit negative impl check. | ||
Both try to apply negative reasoning to prove that an overlap is definitely impossible. | ||
|
||
[`OverlapMode`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/traits/specialization_graph/enum.OverlapMode.html | ||
|
||
## The explicit negative impl check | ||
|
||
This check is done in [`impl_intersection_has_negative_obligation`]. | ||
|
||
This check tries to find a negative trait implementation. | ||
For example: | ||
|
||
```rust | ||
struct MyCustomBox<T: ?Sized>(Box<T>) | ||
|
||
// both in your own crate | ||
impl From<&str> for MyCustomBox<dyn Error> {} | ||
impl<E> From<E> for MyCustomBox<dyn Error> where E: Error {} | ||
``` | ||
|
||
In this example, we'd get: | ||
`MyCustomBox<dyn Error>: From<&str>` and `MyCustomBox<dyn Error>: From<?E>`, giving `?E = &str`. | ||
|
||
And thus, these two implementations would overlap. | ||
However, libstd provides `&str: !Error`, and therefore guarantees that there | ||
will never be a positive implementation of `&str: Error`, and thus there is no overlap. | ||
|
||
Note that for this kind of negative impl check, we must have explicit negative implementations provided. | ||
This is not currently stable. | ||
|
||
[`impl_intersection_has_negative_obligation`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_trait_selection/traits/coherence/fn.impl_intersection_has_impossible_obligation.htmlhttps://doc.rust-lang.org/beta/nightly-rustc/rustc_trait_selection/traits/coherence/fn.impl_intersection_has_negative_obligation.html | ||
|
||
## The implicit negative impl check | ||
|
||
This check is done in [`impl_intersection_has_impossible_obligation`], | ||
and does not rely on negative trait implementations and is stable. | ||
|
||
Let's say there's a | ||
```rust | ||
impl From<MyLocalType> for Box<dyn Error> {} // in your own crate | ||
impl<E> From<E> for Box<dyn Error> where E: Error {} // in std | ||
``` | ||
|
||
This would give: `Box<dyn Error>: From<MyLocalType>`, and `Box<dyn Error>: From<?E>`, | ||
giving `?E = MyLocalType`. | ||
|
||
In your crate there's no `MyLocalType: Error`, downstream crates cannot implement `Error` (a remote trait) for `MyLocalType` (a remote type). | ||
Therefore, these two impls do not overlap. | ||
Importantly, this works even if there isn't a `impl !Error for MyLocalType`. | ||
|
||
[`impl_intersection_has_impossible_obligation`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_trait_selection/traits/coherence/fn.impl_intersection_has_impossible_obligation.html | ||
|
This file contains hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.