-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
regression: cycle detected when computing whether impls specialize one another #125197
Comments
Bisecting this... |
This bisected in #122791. This crate is using specialization, which we don't stably support.
|
@compiler-errors How is that not feature gated? I don't see feature gates in the repos above and presumably it built on stable in order to regress here? |
I am mistaken then, @Mark-Simulacrum. I thought I looked at these crates, but perhaps I was looking at the wrong one. |
I'll look back into this... |
Opened a PR for this and nominated for beta. |
Only compute `specializes` query if (min)specialization is enabled in the crate of the specializing impl Fixes (after backport) rust-lang#125197 ### What rust-lang#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`
Only compute `specializes` query if (min)specialization is enabled in the crate of the specializing impl Fixes (after backport) rust-lang#125197 ### What rust-lang#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`
Only compute `specializes` query if (min)specialization is enabled in the crate of the specializing impl Fixes (after backport) rust-lang/rust#125197 ### What rust-lang/rust#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`
Only compute `specializes` query if (min)specialization is enabled in the crate of the specializing impl Fixes (after backport) rust-lang/rust#125197 ### What rust-lang/rust#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`
ya this was fixed |
The text was updated successfully, but these errors were encountered: