Skip to content

Commit 014ae81

Browse files
Don't consider candidates with no failing where clauses
1 parent 7c4ac06 commit 014ae81

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,36 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
314314
}
315315

316316
fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
317-
// FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
317+
// Filter out the candidates that aren't either error or ambiguous (depending
318+
// on what we are looking for).
319+
let mut candidates = goal
320+
.candidates()
321+
.into_iter()
322+
.filter(|candidate| match self.consider_ambiguities {
323+
true => matches!(candidate.result(), Ok(Certainty::Maybe(_))),
324+
false => matches!(candidate.result(), Err(_)),
325+
})
326+
.collect::<Vec<_>>();
327+
328+
// Throw out candidates that have no failing WC (or higher-ranked obligations,
329+
// for which there should only be one candidate anyways -- but I digress).
318330
// This most likely means that the goal just didn't unify at all, e.g. a param
319331
// candidate with an alias in it.
320-
let candidates = goal.candidates();
332+
if candidates.len() > 1 {
333+
candidates.retain(|candidate| {
334+
goal.infcx().probe(|_| {
335+
candidate.instantiate_nested_goals(self.span()).iter().any(|nested_goal| {
336+
matches!(
337+
nested_goal.source(),
338+
GoalSource::ImplWhereBound | GoalSource::InstantiateHigherRanked
339+
) && match self.consider_ambiguities {
340+
true => matches!(nested_goal.result(), Ok(Certainty::Maybe(_))),
341+
false => matches!(nested_goal.result(), Err(_)),
342+
}
343+
})
344+
})
345+
});
346+
}
321347

322348
let [candidate] = candidates.as_slice() else {
323349
return ControlFlow::Break(self.obligation.clone());
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
trait Foo {}
2+
trait Bar {}
3+
4+
impl<T> Foo for T where T: Bar {}
5+
fn needs_foo(_: impl Foo) {}
6+
7+
trait Mirror {
8+
type Mirror;
9+
}
10+
impl<T> Mirror for T {
11+
type Mirror = T;
12+
}
13+
14+
// Make sure the `Alias: Foo` bound doesn't "shadow" the impl, since the
15+
// impl is really the only candidate we care about here for the purpose
16+
// of error reporting.
17+
fn hello<T>() where <T as Mirror>::Mirror: Foo {
18+
needs_foo(());
19+
//~^ ERROR the trait bound `(): Foo` is not satisfied
20+
}
21+
22+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: the trait bound `(): Foo` is not satisfied
2+
--> $DIR/where-clause-doesnt-apply.rs:18:15
3+
|
4+
LL | needs_foo(());
5+
| --------- ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: required for `()` to implement `Foo`
10+
--> $DIR/where-clause-doesnt-apply.rs:4:9
11+
|
12+
LL | impl<T> Foo for T where T: Bar {}
13+
| ^^^ ^ --- unsatisfied trait bound introduced here
14+
note: required by a bound in `needs_foo`
15+
--> $DIR/where-clause-doesnt-apply.rs:5:22
16+
|
17+
LL | fn needs_foo(_: impl Foo) {}
18+
| ^^^ required by this bound in `needs_foo`
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)