-
Notifications
You must be signed in to change notification settings - Fork 182
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
Recursive solver reports ambiguity #727
Comments
This seems to be a general issue with how chalk handles elaborating environment clauses. The second test case here shows this best, there are two different FromEnv traits that are both elaborated to give the same thing. The recursive solver considers this ambiguous. Other test cases#[test]
fn impl_that_should_work() {
test!(
program {
#[non_enumerable] #[object_safe]
trait Database {}
#[non_enumerable]
trait QueryGroup
{
type DynDb: Database + HasQueryGroup<Self>;
}
#[non_enumerable] #[object_safe]
trait HasQueryGroup<G>
where
Self: Database,
G: QueryGroup,
{ }
struct HelloWorldStorage {}
impl QueryGroup for HelloWorldStorage {
type DynDb = dyn HasQueryGroup<HelloWorldStorage> + 'static;
}
}
goal {
forall<T> {
if (FromEnv(T: HasQueryGroup<HelloWorldStorage>)) {
T: Database
}
}
} yields[SolverChoice::slg_default()] {
"Unique"
} yields[SolverChoice::recursive_default()] { // fails: "Ambiguous; no inference guidance"
"Unique"
}
);
}
#[test]
fn impl_that_should_work2() {
test!(
program {
#[non_enumerable]
trait Database {}
#[non_enumerable]
trait HasQueryGroup<G>
where
Self: Database,
{ }
struct HelloWorldStorage {}
impl Database for HelloWorldStorage { }
}
goal {
forall<T, S> {
if (FromEnv(HelloWorldStorage: HasQueryGroup<T>); FromEnv(HelloWorldStorage: HasQueryGroup<S>)) {
HelloWorldStorage: Database
}
}
} yields[SolverChoice::slg_default()] {
"Unique"
} yields[SolverChoice::recursive_default()] { // fails: "Ambiguous; no inference guidance"
"Unique"
}
);
} |
Yeah. It's actually surprising that this doesn't work though, since solutions do get combined using chalk/chalk-solve/src/solve.rs Lines 64 to 89 in 10ba203
and if the solution doesn't have variables and is unique, the self == other condition should trigger, right? Is the problem that there's somehow an intermediate solution where there's a variable involved? 🤔
|
I've also noticed that removing |
I think the original case is actually the same problem as I investigated in #750. @matthewjasper's (To elaborate on
Contrary to the original case and #750, there are no associated types and no floundering involved here. |
So I have a simple fix that addresses the case from the OP and The code that "combines" results in the recursive solver is actually a bit overconservative. In particular, this logic: chalk/chalk-recursive/src/solve.rs Lines 157 to 160 in f470f2f
is incorrect. That would be reasonable if all of the clauses had to be true, but in fact any of the clauses can be true and they are all equally valid. So the fact that one clause was ambiguous isn't a problem if other clauses are not. To make the tests pass, you also have to adjust the chalk/chalk-solve/src/solve.rs Lines 44 to 64 in f470f2f
As the comment notes, it is not particularly precise. I added a really simple fix to start that just checks whether Unfortunately, this isn't enough to fix that |
So why doesn't We wind up concluding that But then, clever us, we also notice this: trait QueryGroup
{
type DynDb: Database + HasQueryGroup<Self>;
} and so run off trying to prove whether there exists a I'm not sure the best way to fix this just now, it's tied in with some other stuff that I'm in the midst of reconsidering (how we handle assoc type normalization; how best to talk about the WF conditions and implied bounds), but it certainly doesn't seem fatal. The key insight is, that for an implied bound, we're really only interested in normalizations that result from where-clauses, because any normalization that we can derive from an impl means the impl where clause are satisfied and we could as well derive the conclusion from first principles. |
opened #754 |
we only need to prove things one way Partially addresses #727 (some work is left for future work).
In rust-lang/rust-analyzer#9990 we've found this failing test:
Removing
DB: Database
bound andFromEnv(T: Database)
makes the test pass.The text was updated successfully, but these errors were encountered: