diff --git a/chalk-solve/src/solve/slg/aggregate.rs b/chalk-solve/src/solve/slg/aggregate.rs index bdd4068adcb..b389ed56877 100644 --- a/chalk-solve/src/solve/slg/aggregate.rs +++ b/chalk-solve/src/solve/slg/aggregate.rs @@ -70,6 +70,10 @@ impl context::AggregateOps> 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)) { diff --git a/tests/test/misc.rs b/tests/test/misc.rs index a3d76bf00f7..e62f9b2c656 100644 --- a/tests/test/misc.rs +++ b/tests/test/misc.rs @@ -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 { } + struct A { } + + impl IntoIterator for Ref { } + impl IntoIterator for Ref where T: OtherTrait { } + } + + goal { + exists { Ref: 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 { } + struct A { } + struct B { } + struct C { } + + struct D { } + + impl IntoIterator for Ref { type Item = Ref; } + impl IntoIterator for Ref { type Item = Ref; } + impl IntoIterator for Ref { type Item = Ref; } + impl IntoIterator for Ref { type Item = D; } + } + + goal { + exists { + Normalize( 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.