1
Fork 0

Only consider ambiguous goals when finding best obligation for ambiguities

This commit is contained in:
Michael Goulet 2024-05-03 20:08:35 -04:00
parent d7ea27808d
commit 6714216eaa
3 changed files with 24 additions and 20 deletions

View file

@ -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,
}));
@ -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(_)) => {
@ -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,
}
@ -275,12 +275,13 @@ 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)
@ -288,6 +289,7 @@ fn find_best_leaf_obligation<'tcx>(
struct BestObligation<'tcx> {
obligation: PredicateObligation<'tcx>,
consider_ambiguities: bool,
}
impl<'tcx> BestObligation<'tcx> {
@ -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))?;