Skip to content

Commit

Permalink
Don't return definite guidance if we find one solution and then flounder
Browse files Browse the repository at this point in the history
If we find one solution and then flounder, this previously resulted in a
`Guidance::Definite` result. I think the reason is that `any_future_answer` has
no answers to check and hence returns true.
  • Loading branch information
flodiebold committed Apr 14, 2020
1 parent 2bd2e03 commit 9d655f4
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
4 changes: 4 additions & 0 deletions chalk-solve/src/solve/slg/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ impl<I: Interner> context::AggregateOps<SlgContext<I>> for SlgContextOps<'_, I>
break Guidance::Unknown;
}

if let AnswerResult::Floundered = answers.peek_answer(|| should_continue()) {
break Guidance::Unknown;
}

if !answers
.any_future_answer(|ref mut new_subst| new_subst.may_invalidate(interner, &subst))
{
Expand Down
57 changes: 57 additions & 0 deletions tests/test/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,63 @@ fn flounder() {
}
}

/// Don't return definite guidance if we flounder after finding one solution.
#[test]
fn flounder_ambiguous() {
test! {
program {
trait IntoIterator { }
#[non_enumerable]
trait OtherTrait { }

struct Ref<T> { }
struct A { }

impl IntoIterator for Ref<A> { }
impl<T> IntoIterator for Ref<T> where T: OtherTrait { }
}

goal {
exists<T> { Ref<T>: IntoIterator }
} yields {
"Ambiguous; no inference guidance"
}
}
}

/// Don't return definite guidance if we are able to merge two solutions and the
/// third one matches that as well (the fourth may not).
#[test]
fn normalize_ambiguous() {
test! {
program {
trait IntoIterator { type Item; }

struct Ref<T> { }
struct A { }
struct B { }
struct C { }

struct D { }

impl IntoIterator for Ref<A> { type Item = Ref<A>; }
impl IntoIterator for Ref<B> { type Item = Ref<B>; }
impl IntoIterator for Ref<C> { type Item = Ref<C>; }
impl IntoIterator for Ref<D> { type Item = D; }
}

goal {
exists<T, U> {
Normalize(<Ref<T> as IntoIterator>::Item -> U)
}
} yields {
// FIXME: this is wrong!
"Ambiguous; definite substitution"
// "Ambiguous; no inference guidance"
}
}
}

// Test that, when solving `?T: Sized`, we only wind up pulling a few
// answers before we stop.
// Also tests that we search breadth-first.
Expand Down

0 comments on commit 9d655f4

Please sign in to comment.