-
Notifications
You must be signed in to change notification settings - Fork 0
-Ztrait-solver=next-coherence
: issue-90662-projection-caching.rs breaks
#70
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
Comments
I suspect alias relate doesnt fail because the
This is commented on a little in the function already: if let Certainty::OVERFLOW = certainty {
// If we have overflow, it's probable that we're substituting a type
// into itself infinitely and any partial substitutions in the query
// response are probably not useful anyways, so just return an empty
// query response.
//
// This may prevent us from potentially useful inference, e.g.
// 2 candidates, one ambiguous and one overflow, which both
// have the same inference constraints.
//
// Changing this to retain some constraints in the future
// won't be a breaking change, so this is good enough for now.
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
} I have not actually looked at any debug logs for this though and am mostly just going off reading the provided code snippet and explanation of what's happening in new solver. |
For the record, these tests hang if that hack is removed.
|
similar example: unlike a "true" inductive cycle this avoids fatal overflow in the new solver and an endlessly growing fixpoint cycle in the new one trait Trait {
type Assoc;
}
struct W<T: ?Sized>(*mut T);
impl<T: ?Sized> Trait for W<W<T>>
where
W<T>: Trait,
{
type Assoc = ();
}
trait NoOverlap {}
impl<T: Trait<Assoc = u32>> NoOverlap for T {}
impl<T: ?Sized> NoOverlap for W<T> {}
fn main() {} |
-Znext-solver: adapt overflow rules to avoid breakage Do not erase overflow constraints if they are from equating the impl header when normalizing[^1]. This should be the minimal change to not break crates depending on the old project behavior of "apply impl constraints while only lazily evaluating any nested goals". Fixes rust-lang/trait-system-refactor-initiative#70, see https://hackmd.io/ATf4hN0NRY-w2LIVgeFsVg for the reasoning behind this. Only keeping constraints on overflow for `normalize-to` goals as that's the only thing needed for backcompat. It also allows us to not track the origin of root obligations. The issue with root goals would be something like the following: ```rust trait Foo {} trait Bar {} trait FooBar {} impl<T: Foo + Bar> FooBar for T {} // These two should behave the same, rn we can drop constraints for both, // but if we don't drop `Misc` goals we would only drop the constraints for // `FooBar` unless we track origins of root obligations. fn func1<T: Foo + Bar>() {} fn func2<T: FooBaz>() {} ``` [^1]: mostly, the actual rules are slightly different r? `@compiler-errors`
Rollup merge of rust-lang#119071 - lcnr:overflowo, r=compiler-errors -Znext-solver: adapt overflow rules to avoid breakage Do not erase overflow constraints if they are from equating the impl header when normalizing[^1]. This should be the minimal change to not break crates depending on the old project behavior of "apply impl constraints while only lazily evaluating any nested goals". Fixes rust-lang/trait-system-refactor-initiative#70, see https://hackmd.io/ATf4hN0NRY-w2LIVgeFsVg for the reasoning behind this. Only keeping constraints on overflow for `normalize-to` goals as that's the only thing needed for backcompat. It also allows us to not track the origin of root obligations. The issue with root goals would be something like the following: ```rust trait Foo {} trait Bar {} trait FooBar {} impl<T: Foo + Bar> FooBar for T {} // These two should behave the same, rn we can drop constraints for both, // but if we don't drop `Misc` goals we would only drop the constraints for // `FooBar` unless we track origins of root obligations. fn func1<T: Foo + Bar>() {} fn func2<T: FooBaz>() {} ``` [^1]: mostly, the actual rules are slightly different r? ``@compiler-errors``
minimized https://rust.godbolt.org/z/MK6hWKhdb
for whatever reason
dyn Repository
breaks,()
does not.why this compiles in the old solver:
Projection(<ServiceImpl as Provider<TestModule>>::Interface)
TestModule: HasProvider<&'static ()>
is simply emitted as a nested goal, successfully normalize toService
impl HasProvider<&'static ()> for TestModule {}
withimpl HasProvider<Service> for TestModule {}
failswhat's happening in the new solver:
alias-relate(<ServiceImpl as Provider<TestModule>>::Interface, &'static ())
exists<'0> alias-relate(<ServiceImpl as Provider<TestModule>>::Interface, &'0 ())
Service
with nested goalTestModule: HasProvider<&'static ()>
, again, canonicalized to'0
impl HasProvider<&'static ()> for TestModule {}
, YES'0 == 'static
impl HasProvider<<ServiceImpl as Provider<TestModule>>::Interface> for TestModule {}
<ServiceImpl as Provider<TestModule>>::Interface
with&'static ()
, resulting in an inductive cycleThe text was updated successfully, but these errors were encountered: