Skip to content

Commit 8fc6554

Browse files
committed
merge piece on overlap checks with docs about coherence (based on review comments)
1 parent a29b0ae commit 8fc6554

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

src/SUMMARY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@
137137
- [Caching subtleties](./traits/caching.md)
138138
- [Implied bounds](./traits/implied-bounds.md)
139139
- [Specialization](./traits/specialization.md)
140-
- [Overlap checks](./traits/overlap.md)
141140
- [Chalk-based trait solving](./traits/chalk.md)
142141
- [Lowering to logic](./traits/lowering-to-logic.md)
143142
- [Goals and clauses](./traits/goals-and-clauses.md)
@@ -157,6 +156,7 @@
157156
- [Type checking](./type-checking.md)
158157
- [Method Lookup](./method-lookup.md)
159158
- [Variance](./variance.md)
159+
- [Coherence Checking](./coherence.md)
160160
- [Opaque Types](./opaque-types-type-alias-impl-trait.md)
161161
- [Inference details](./opaque-types-impl-trait-inference.md)
162162
- [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md)

src/traits/overlap.md renamed to src/coherence.md

+37-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
1-
# Overlap checks
21

3-
As part of checking items (specifically: structs, enums, traits, unions),
4-
the compiler checks whether impl blocks overlap, for example because they define the same functions.
5-
This is an example an overlap check.
6-
The same overlap check is done when constructing a [specialization graph](./specialization.md).
7-
Here, trait implementations could overlap, for example because of a conflicting blanket implementation overlapping with some specific implementation.
2+
# Coherence
83

9-
The overlap check always compares two impls.
10-
In the case of inherent impl blocks, this means that at least for small n,
11-
rustc quite literally compares each impl to each other impl block in an `n^2` loop
12-
(see `fn check_item` in coherence/inherent_impls_overlap.rs).
4+
> NOTE: this is based on [notes by @lcnr](https://github.com/rust-lang/rust/pull/121848)
5+
6+
Coherence checking is what detects both of trait impls and inherent impls overlapping with others.
7+
(reminder: [inherent impls](https://doc.rust-lang.org/reference/items/implementations.html#inherent-implementations) are impls of concrete types like `impl MyStruct {}`)
8+
9+
Overlapping trait impls always produce an error,
10+
while overlapping inherent impls result in an error only if they have methods with the same name.
11+
12+
Checking for overlaps is split in two parts. First there's the [overlap check(s)](#overlap-checks),
13+
which finds overlaps between traits and inherent implementations that the compiler currently knows about.
14+
15+
However, Coherence also results in an error if any other impls **could** exist,
16+
even if they are currently unknown.
17+
This affects impls which may get added to upstream crates in a backwards compatible way,
18+
and impls from downstream crates.
19+
This is called the Orphan check.
20+
21+
## Overlap checks
22+
23+
Overlap checks are performed for both inherent impls, and for trait impls.
24+
This uses the same overlap checking code, really done as two separate analyses.
25+
Overlap checks always consider pairs of implementations, comparing them to each other.
26+
27+
Overlap checking for inherent impl blocks is done through `fn check_item` in coherence/inherent_impls_overlap.rs),
28+
where you can very clearly see that (at least for small `n`), the check really performs `n^2`
29+
comparisons between impls.
30+
31+
In the case of traits, this check is currently done as part of building the [specialization graph](./specialization.md),
32+
to handle specializing impls overlapping with their parent, but this may change in the future.
33+
34+
In both cases, all pairs of impls are checked for overlap.
1335

1436
Overlapping is sometimes partially allowed:
37+
1538
1. for maker traits
1639
2. under [specialization](./specialization.md)
1740

@@ -23,7 +46,7 @@ Both try to apply negative reasoning to prove that an overlap is definitely impo
2346

2447
[`OverlapMode`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/traits/specialization_graph/enum.OverlapMode.html
2548

26-
## The explicit negative impl check
49+
### The explicit negative impl check
2750

2851
This check is done in [`impl_intersection_has_negative_obligation`].
2952

@@ -50,7 +73,7 @@ This is not currently stable.
5073

5174
[`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
5275

53-
## The implicit negative impl check
76+
### The implicit negative impl check
5477

5578
This check is done in [`impl_intersection_has_impossible_obligation`],
5679
and does not rely on negative trait implementations and is stable.
@@ -70,3 +93,5 @@ Importantly, this works even if there isn't a `impl !Error for MyLocalType`.
7093

7194
[`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
7295

96+
97+

src/solve/invariants.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ in the trait solver
113113

114114
#### The type system is complete during the implicit negative overlap check in coherence ✅
115115

116-
For more on overlap checking: [./overlap.md]
116+
For more on overlap checking: [../coherence.md]
117117

118118
During the implicit negative overlap check in coherence we must never return *error* for
119119
goals which can be proven. This would allow for overlapping impls with potentially different

src/traits/specialization.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Defined in the `specialize` module.
66

77
The basic strategy is to build up a *specialization graph* during
8-
coherence checking (coherence checking looks for [overlapping impls](./overlap.md)).
8+
coherence checking (coherence checking looks for [overlapping impls](../coherence.md)).
99
Insertion into the graph locates the right place
1010
to put an impl in the specialization hierarchy; if there is no right
1111
place (due to partial overlap but no containment), you get an overlap

0 commit comments

Comments
 (0)