Skip to content

Commit

Permalink
Only consider ambiguous goals when finding best obligation for ambigu…
Browse files Browse the repository at this point in the history
…ities
  • Loading branch information
compiler-errors committed May 4, 2024
1 parent 34e91ec commit 4bbaf66
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
20 changes: 11 additions & 9 deletions compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
.collect();

errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
obligation: find_best_leaf_obligation(infcx, &obligation),
obligation: find_best_leaf_obligation(infcx, &obligation, true),
code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
root_obligation: obligation,
}));
Expand Down Expand Up @@ -198,7 +198,7 @@ fn fulfillment_error_for_no_solution<'tcx>(
infcx: &InferCtxt<'tcx>,
root_obligation: PredicateObligation<'tcx>,
) -> FulfillmentError<'tcx> {
let obligation = find_best_leaf_obligation(infcx, &root_obligation);
let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);

let code = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
Expand Down Expand Up @@ -266,7 +266,7 @@ fn fulfillment_error_for_stalled<'tcx>(
});

FulfillmentError {
obligation: find_best_leaf_obligation(infcx, &obligation),
obligation: find_best_leaf_obligation(infcx, &obligation, true),
code,
root_obligation: obligation,
}
Expand All @@ -275,19 +275,21 @@ fn fulfillment_error_for_stalled<'tcx>(
fn find_best_leaf_obligation<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>,
consider_ambiguities: bool,
) -> PredicateObligation<'tcx> {
let obligation = infcx.resolve_vars_if_possible(obligation.clone());
infcx
.visit_proof_tree(
obligation.clone().into(),
&mut BestObligation { obligation: obligation.clone() },
&mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
)
.break_value()
.unwrap_or(obligation)
}

struct BestObligation<'tcx> {
obligation: PredicateObligation<'tcx>,
consider_ambiguities: bool,
}

impl<'tcx> BestObligation<'tcx> {
Expand Down Expand Up @@ -355,11 +357,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
}
}

// Skip nested goals that hold.
//FIXME: We should change the max allowed certainty based on if we're
// visiting an ambiguity or error obligation.
if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
continue;
// Skip nested goals that aren't the *reason* for our goal's failure.
match self.consider_ambiguities {
true if matches!(nested_goal.result(), Ok(Certainty::Maybe(_))) => {}
false if matches!(nested_goal.result(), Err(_)) => {}
_ => continue,
}

self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ where
// entering the cycle from `A` fails, but would work if we were to use the cache
// result of `B<X>`.
impls_trait::<A<X>, _, _, _>();
//~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
//~^ ERROR the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied
}

fn main() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
error[E0277]: the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied
--> $DIR/incompleteness-unstable-result.rs:63:19
|
LL | impls_trait::<A<X>, _, _, _>();
| ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>`
| ^^^^ the trait `Trait<i32, u8, u8>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
|
= help: the following other types implement trait `IncompleteGuidance<T, V>`:
<T as IncompleteGuidance<U, i16>>
<T as IncompleteGuidance<U, i8>>
<T as IncompleteGuidance<U, u8>>
note: required for `A<X>` to implement `Trait<_, _, u8>`
note: required for `A<X>` to implement `Trait<i32, u8, u8>`
--> $DIR/incompleteness-unstable-result.rs:32:50
|
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
| ^^^^^^^^^^^^^^ ^^^^
LL | where
LL | T: IncompleteGuidance<U, V>,
| ------------------------ unsatisfied trait bound introduced here
...
LL | A<T>: Trait<U, D, V>,
| -------------- unsatisfied trait bound introduced here
= note: 8 redundant requirements hidden
= note: required for `A<X>` to implement `Trait<i32, u8, u8>`
note: required by a bound in `impls_trait`
--> $DIR/incompleteness-unstable-result.rs:51:28
|
LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
|
LL | X: IncompleteGuidance<u32, i16>, A<X>: Trait<i32, u8, u8>
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 1 previous error

Expand Down

0 comments on commit 4bbaf66

Please sign in to comment.