You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Auto merge of #126139 - compiler-errors:specializes, r=<try>
Only compute `specializes` query if (min)specialization is enabled in the crate of the specializing impl
Fixes (after backport) #125197
### What
#122791 makes it so that inductive cycles are no longer hard errors. That means that when we are testing, for example, whether these impls overlap:
```rust
impl PartialEq<Self> for AnyId {
fn eq(&self, _: &Self) -> bool {
todo!()
}
}
impl<T: Identifier> PartialEq<T> for AnyId {
fn eq(&self, _: &T) -> bool {
todo!()
}
}
```
...given...
```rust
pub trait Identifier: Display + 'static {}
impl<T> Identifier for T where T: PartialEq + Display + 'static {}
```
Then we try to see if the second impl holds given `T = AnyId`. That requires `AnyId: Identifier`, which requires that `AnyId: PartialEq`, which is satisfied by these two impl candidates... The `PartialEq<T>` impl is a cycle, and we used to winnow it when we used to treat inductive cycles as errors.
However, now that we don't winnow it, this means that we *now* try calling `candidate_should_be_dropped_in_favor_of`, which tries to check whether one of the impls specializes the other: the `specializes` query. In that query, we currently bail early if the impl is local:
However, in a foreign crate, we try to compute if the two impls specialize each other by doing trait solving. This may itself lead to the same situation where we call `specializes`, which will lead to a query cycle.
### How does this fix the problem
We now record whether specialization is enabled in foreign crates, and extend this early-return behavior to foreign impls too. This means that we can only encounter these cycles if we truly have a specializing impl from a crate with specialization enabled.
-----
r? `@oli-obk` or `@lcnr`
// Makes sure that we don't check `specializes(impl1, impl2)` for a pair of impls that don't
5
+
// actually participate in specialization. Since <https://github.com/rust-lang/rust/pull/122791>,
6
+
// we don't treat inductive cycles as errors -- so we may need to winnow more pairs of impls, and
7
+
// we try to winnow impls in favor of other impls. However, if we're *inside* the `specializes`
8
+
// query, then may have a query cycle if we call `specializes` again!
0 commit comments