-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix replacing supertrait aliases in ReplaceProjectionWith
#139774
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
Conversation
Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor |
nested: Vec<Goal<I, I::Predicate>>, | ||
is_ambiguous: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we'd use a FallibleTypeFolder
here rather than tracking ambiguity on the side. Unfortunately, I think it's impossible to implement a FallibleTypeFolder
b/c of the blanket implementation:
impl FallibleTypeFolder<I> for F where F: TypeFolder<I> {}
...causing us to have impl overlap due to downstream impl ambiguity in coherence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:skull_emoji:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would like to block this on #139768 then
compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
Show resolved
Hide resolved
Want to familiarize myself with why exactly this folder is necessary again. A quick look at the comments and the link to lcnr/solver-woes#9 / rust-lang/trait-system-refactor-initiative#6 were not too unhelpful at getting this back into cache. |
Yeah, the documentation is lacking in the compiler. It mentions the need for this folder to prevent unsoundness due to aliases trivially proving their own item bounds, but it doesn't mention that this folder is also required to prevent trivial (in the future -- coinductive, I think) cycles due to the fact that we require alias bounds to hold in the built-in impl. This is made further interesting by the fact that aliases are allowed to be present in item bounds, for example see: trait Foo {
type Assoc: Baz<Self::Assoc>;
}
trait Baz<T> {}
impl Baz<()> for () {}
fn is_foo<T: Foo + ?Sized>() {}
fn main() {
is_foo::<dyn Foo<Assoc = ()>>();
} Such a built-in impl conceptually expands to something like: impl<A> Foo for dyn Foo<Assoc = A>
where
<Self as Foo>::Assoc: Baz<<Self as Foo>::Assoc>
{
type Assoc = A;
} Which I hope is clear that it'll lead to cycles :) |
f803ce7
to
7e1be05
Compare
Actually, the documentation already mentions a very similar example to the one I gave above:
I kinda feel like that is sufficient to motivate the existence of the folder, and I'll just remove the FIXME since it's not necessary anymore. |
compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
Outdated
Show resolved
Hide resolved
965c784
to
969f531
Compare
969f531
to
e1936d2
Compare
gamer @bors r+ rollup |
…r=lcnr Fix replacing supertrait aliases in `ReplaceProjectionWith` The new solver has a procedure called `predicates_for_object_candidate`, which elaborates the super-bounds and item-bounds that are required to hold for a dyn trait to implement something via a built-in object impl. In that procedure, there is a folder called `ReplaceProjectionWith` which is responsible for replacing projections that reference `Self`, so that we don't encounter cycles when we then go on to normalize those projections in the process of proving these super-bounds. That folder had a few problems: Firstly, it wasn't actually checking that this was a super bound originating from `Self`. Secondly, it only accounted for a *single* projection type def id, but trait objects can have multiple (i.e. `trait Foo<A, B>: Bar<A, Assoc = A> + Bar<B, Assoc = B>`). To fix the first, it's simple enough to just add an equality check for the self ty. To fix the second, I implemented a matching step that's very similar to the `projection_may_match` check we have for upcasting, since on top of having multiple choices, we need to deal with both non-structural matches and ambiguity. This probably lacks a bit of documentation, but I think it works pretty well. Fixes rust-lang/trait-system-refactor-initiative#171 r? lcnr
…r=lcnr Fix replacing supertrait aliases in `ReplaceProjectionWith` The new solver has a procedure called `predicates_for_object_candidate`, which elaborates the super-bounds and item-bounds that are required to hold for a dyn trait to implement something via a built-in object impl. In that procedure, there is a folder called `ReplaceProjectionWith` which is responsible for replacing projections that reference `Self`, so that we don't encounter cycles when we then go on to normalize those projections in the process of proving these super-bounds. That folder had a few problems: Firstly, it wasn't actually checking that this was a super bound originating from `Self`. Secondly, it only accounted for a *single* projection type def id, but trait objects can have multiple (i.e. `trait Foo<A, B>: Bar<A, Assoc = A> + Bar<B, Assoc = B>`). To fix the first, it's simple enough to just add an equality check for the self ty. To fix the second, I implemented a matching step that's very similar to the `projection_may_match` check we have for upcasting, since on top of having multiple choices, we need to deal with both non-structural matches and ambiguity. This probably lacks a bit of documentation, but I think it works pretty well. Fixes rust-lang/trait-system-refactor-initiative#171 r? lcnr
…iaskrgr Rollup of 9 pull requests Successful merges: - rust-lang#139774 (Fix replacing supertrait aliases in `ReplaceProjectionWith`) - rust-lang#139850 (Hide unstable print kinds within emit_unknown_print_request_help in stable channel) - rust-lang#139870 (add retries to remove and create dir all) - rust-lang#139902 (do not emit `OpaqueCast` projections with `-Znext-solver`) - rust-lang#139931 (bootstrap: enable zlib for LLVM for Windows GNU) - rust-lang#139935 (Upgrade to `rustc-rayon-core` 0.5.1) - rust-lang#139943 (rustdoc: Support inlined cross-crate re-exported trait aliases) - rust-lang#139961 (Two `rustc_const_eval` cleanups) - rust-lang#139962 (opt-dist: add a flag for running tests) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#139774 - compiler-errors:supertrait-alias, r=lcnr Fix replacing supertrait aliases in `ReplaceProjectionWith` The new solver has a procedure called `predicates_for_object_candidate`, which elaborates the super-bounds and item-bounds that are required to hold for a dyn trait to implement something via a built-in object impl. In that procedure, there is a folder called `ReplaceProjectionWith` which is responsible for replacing projections that reference `Self`, so that we don't encounter cycles when we then go on to normalize those projections in the process of proving these super-bounds. That folder had a few problems: Firstly, it wasn't actually checking that this was a super bound originating from `Self`. Secondly, it only accounted for a *single* projection type def id, but trait objects can have multiple (i.e. `trait Foo<A, B>: Bar<A, Assoc = A> + Bar<B, Assoc = B>`). To fix the first, it's simple enough to just add an equality check for the self ty. To fix the second, I implemented a matching step that's very similar to the `projection_may_match` check we have for upcasting, since on top of having multiple choices, we need to deal with both non-structural matches and ambiguity. This probably lacks a bit of documentation, but I think it works pretty well. Fixes rust-lang/trait-system-refactor-initiative#171 r? lcnr
The new solver has a procedure called
predicates_for_object_candidate
, which elaborates the super-bounds and item-bounds that are required to hold for a dyn trait to implement something via a built-in object impl.In that procedure, there is a folder called
ReplaceProjectionWith
which is responsible for replacing projections that referenceSelf
, so that we don't encounter cycles when we then go on to normalize those projections in the process of proving these super-bounds.That folder had a few problems: Firstly, it wasn't actually checking that this was a super bound originating from
Self
. Secondly, it only accounted for a single projection type def id, but trait objects can have multiple (i.e.trait Foo<A, B>: Bar<A, Assoc = A> + Bar<B, Assoc = B>
).To fix the first, it's simple enough to just add an equality check for the self ty. To fix the second, I implemented a matching step that's very similar to the
projection_may_match
check we have for upcasting, since on top of having multiple choices, we need to deal with both non-structural matches and ambiguity.This probably lacks a bit of documentation, but I think it works pretty well.
Fixes rust-lang/trait-system-refactor-initiative#171
r? lcnr