rename select_where_possible and select_all_or_error

This commit is contained in:
Boxy Uwu
2025-09-28 00:22:36 +01:00
parent d62f33a7c6
commit 8e9b0c4ca9
74 changed files with 170 additions and 145 deletions

View File

@@ -420,7 +420,7 @@ fn try_extract_error_from_fulfill_cx<'a, 'tcx>(
// We generally shouldn't have errors here because the query was // We generally shouldn't have errors here because the query was
// already run, but there's no point using `span_delayed_bug` // already run, but there's no point using `span_delayed_bug`
// when we're going to emit an error here anyway. // when we're going to emit an error here anyway.
let _errors = ocx.select_all_or_error(); let _errors = ocx.evaluate_obligations_error_on_ambiguity();
let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone()); let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
try_extract_error_from_region_constraints( try_extract_error_from_region_constraints(
ocx.infcx, ocx.infcx,

View File

@@ -1313,7 +1313,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let ocx = ObligationCtxt::new_with_diagnostics(self.infcx); let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
let cause = ObligationCause::misc(expr.span, self.mir_def_id()); let cause = ObligationCause::misc(expr.span, self.mir_def_id());
ocx.register_bound(cause, self.infcx.param_env, ty, clone_trait); ocx.register_bound(cause, self.infcx.param_env, ty, clone_trait);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.iter().all(|error| { if errors.iter().all(|error| {
match error.obligation.predicate.as_clause().and_then(|c| c.as_trait_clause()) { match error.obligation.predicate.as_clause().and_then(|c| c.as_trait_clause()) {
Some(clause) => match clause.self_ty().skip_binder().kind() { Some(clause) => match clause.self_ty().skip_binder().kind() {
@@ -1497,7 +1497,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let cause = ObligationCause::misc(span, self.mir_def_id()); let cause = ObligationCause::misc(span, self.mir_def_id());
ocx.register_bound(cause, self.infcx.param_env, ty, def_id); ocx.register_bound(cause, self.infcx.param_env, ty, def_id);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
// Only emit suggestion if all required predicates are on generic // Only emit suggestion if all required predicates are on generic
let predicates: Result<Vec<_>, _> = errors let predicates: Result<Vec<_>, _> = errors

View File

@@ -1134,7 +1134,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
Obligation::misc(tcx, span, self.mir_def_id(), self.infcx.param_env, pred) Obligation::misc(tcx, span, self.mir_def_id(), self.infcx.param_env, pred)
})); }));
if ocx.select_all_or_error().is_empty() && count > 0 { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() && count > 0 {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(), tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(),
fluent::borrowck_dereference_suggestion, fluent::borrowck_dereference_suggestion,

View File

@@ -657,7 +657,7 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
let errors = match dropck_outlives::compute_dropck_outlives_with_errors( let errors = match dropck_outlives::compute_dropck_outlives_with_errors(
&ocx, op, span, &ocx, op, span,
) { ) {
Ok(_) => ocx.select_all_or_error(), Ok(_) => ocx.evaluate_obligations_error_on_ambiguity(),
Err(e) => e, Err(e) => e,
}; };

View File

@@ -139,7 +139,7 @@ pub fn validate_trivial_unsize<'tcx>(
) else { ) else {
return false; return false;
}; };
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return false; return false;
} }
infcx.leak_check(universe, None).is_ok() infcx.leak_check(universe, None).is_ok()

View File

@@ -415,7 +415,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
) )
})); }));
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.is_empty() { if errors.is_empty() {
Some(ConstConditionsHold::Yes) Some(ConstConditionsHold::Yes)
} else { } else {

View File

@@ -119,7 +119,7 @@ impl Qualif for HasMutInterior {
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]), ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
); );
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
!errors.is_empty() !errors.is_empty()
} }
@@ -197,7 +197,7 @@ impl Qualif for NeedsNonConstDrop {
}, },
), ),
)); ));
!ocx.select_all_or_error().is_empty() !ocx.evaluate_obligations_error_on_ambiguity().is_empty()
} }
fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {

View File

@@ -43,5 +43,5 @@ pub fn relate_types<'tcx>(
Ok(()) => {} Ok(()) => {}
Err(_) => return false, Err(_) => return false,
}; };
ocx.select_all_or_error().is_empty() ocx.evaluate_obligations_error_on_ambiguity().is_empty()
} }

View File

@@ -199,7 +199,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
// evaluate/fulfill mismatches, but that's not a reason for an ICE. // evaluate/fulfill mismatches, but that's not a reason for an ICE.
return None; return None;
}; };
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
if self.infcx.next_trait_solver() { if self.infcx.next_trait_solver() {
unreachable!(); unreachable!();

View File

@@ -235,7 +235,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
// They can probably get removed with better treatment of the new `DropImpl` // They can probably get removed with better treatment of the new `DropImpl`
// obligation cause code, and perhaps some custom logic in `report_region_errors`. // obligation cause code, and perhaps some custom logic in `report_region_errors`.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let mut guar = None; let mut guar = None;
let mut root_predicates = FxHashSet::default(); let mut root_predicates = FxHashSet::default();

View File

@@ -375,7 +375,7 @@ fn check_opaque_meets_bounds<'tcx>(
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// version. // version.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let guar = infcx.err_ctxt().report_fulfillment_errors(errors); let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(guar); return Err(guar);
@@ -2028,7 +2028,7 @@ pub(super) fn check_coroutine_obligations(
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate)); ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
} }
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
debug!(?errors); debug!(?errors);
if !errors.is_empty() { if !errors.is_empty() {
return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
@@ -2072,7 +2072,7 @@ pub(super) fn check_potentially_region_dependent_goals<'tcx>(
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate)); ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
} }
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
debug!(?errors); debug!(?errors);
if errors.is_empty() { Ok(()) } else { Err(infcx.err_ctxt().report_fulfillment_errors(errors)) } if errors.is_empty() { Ok(()) } else { Err(infcx.err_ctxt().report_fulfillment_errors(errors)) }
} }

View File

@@ -363,7 +363,7 @@ fn compare_method_predicate_entailment<'tcx>(
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// version. // version.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors); let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported); return Err(reported);
@@ -669,7 +669,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// RPITs. // RPITs.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig) if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig)
{ {
@@ -1215,7 +1215,7 @@ fn check_region_late_boundedness<'tcx>(
return None; return None;
}; };
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
return None; return None;
} }
@@ -2106,7 +2106,7 @@ fn compare_const_predicate_entailment<'tcx>(
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// version. // version.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
} }
@@ -2242,7 +2242,7 @@ fn compare_type_predicate_entailment<'tcx>(
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// version. // version.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors); let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported); return Err(reported);
@@ -2367,7 +2367,7 @@ pub(super) fn check_type_bounds<'tcx>(
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// version. // version.
ocx.register_obligations(obligations); ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors); let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported); return Err(reported);

View File

@@ -164,7 +164,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
param_env, param_env,
trait_m_sig.inputs_and_output, trait_m_sig.inputs_and_output,
)); ));
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (selection)"); tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (selection)");
return; return;
} }

View File

@@ -138,7 +138,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
let norm_return_ty = ocx.normalize(&cause, param_env, return_ty); let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
ocx.register_bound(cause, param_env, norm_return_ty, term_did); ocx.register_bound(cause, param_env, norm_return_ty, term_did);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(errors); infcx.err_ctxt().report_fulfillment_errors(errors);
error = true; error = true;

View File

@@ -660,7 +660,7 @@ pub fn check_function_signature<'tcx>(
match ocx.eq(&cause, param_env, expected_sig, actual_sig) { match ocx.eq(&cause, param_env, expected_sig, actual_sig) {
Ok(()) => { Ok(()) => {
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
} }

View File

@@ -142,7 +142,7 @@ where
} }
f(&mut wfcx)?; f(&mut wfcx)?;
let errors = wfcx.select_all_or_error(); let errors = wfcx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
} }
@@ -1803,7 +1803,11 @@ fn receiver_is_valid<'tcx>(
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| { if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
let ocx = ObligationCtxt::new(wfcx.infcx); let ocx = ObligationCtxt::new(wfcx.infcx);
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?; ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) } if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
Ok(())
} else {
Err(NoSolution)
}
}) { }) {
return Ok(()); return Ok(());
} }
@@ -1838,7 +1842,11 @@ fn receiver_is_valid<'tcx>(
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| { if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
let ocx = ObligationCtxt::new(wfcx.infcx); let ocx = ObligationCtxt::new(wfcx.infcx);
ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?; ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) } if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
Ok(())
} else {
Err(NoSolution)
}
}) { }) {
wfcx.register_obligations(autoderef.into_obligations()); wfcx.register_obligations(autoderef.into_obligations());
return Ok(()); return Ok(());

View File

@@ -333,7 +333,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
param_env, param_env,
ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]), ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
)); ));
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
if is_from_coerce_pointee_derive(tcx, span) { if is_from_coerce_pointee_derive(tcx, span) {
return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity { return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
@@ -558,7 +558,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
ty::TraitRef::new(tcx, trait_def_id, [source, target]), ty::TraitRef::new(tcx, trait_def_id, [source, target]),
); );
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
if is_from_coerce_pointee_derive(tcx, span) { if is_from_coerce_pointee_derive(tcx, span) {

View File

@@ -315,7 +315,7 @@ fn orphan_check<'tcx>(
let ocx = traits::ObligationCtxt::new(&infcx); let ocx = traits::ObligationCtxt::new(&infcx);
let ty = ocx.normalize(&cause, ty::ParamEnv::empty(), user_ty); let ty = ocx.normalize(&cause, ty::ParamEnv::empty(), user_ty);
let ty = infcx.resolve_vars_if_possible(ty); let ty = infcx.resolve_vars_if_possible(ty);
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
return Ok(user_ty); return Ok(user_ty);
} }

View File

@@ -1267,7 +1267,7 @@ pub fn suggest_impl_trait<'tcx>(
Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args), Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
); );
// FIXME(compiler-errors): We may benefit from resolving regions here. // FIXME(compiler-errors): We may benefit from resolving regions here.
if ocx.select_where_possible().is_empty() if ocx.try_evaluate_obligations().is_empty()
&& let item_ty = infcx.resolve_vars_if_possible(item_ty) && let item_ty = infcx.resolve_vars_if_possible(item_ty)
&& let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None) && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
&& let Some(sugg) = formatter( && let Some(sugg) = formatter(

View File

@@ -95,7 +95,7 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(tcx_ty.into())), ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(tcx_ty.into())),
)); ));
for error in ocx.select_all_or_error() { for error in ocx.evaluate_obligations_error_on_ambiguity() {
debug!("Wf-check got error for {:?}: {:?}", ty, error); debug!("Wf-check got error for {:?}: {:?}", ty, error);
if error.obligation.predicate == self.predicate { if error.obligation.predicate == self.predicate {
// Save the cause from the greatest depth - this corresponds // Save the cause from the greatest depth - this corresponds

View File

@@ -183,7 +183,7 @@ fn get_impl_args(
&ObligationCause::misc(impl1_span, impl1_def_id), &ObligationCause::misc(impl1_span, impl1_def_id),
); );
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors); let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(guar); return Err(guar);

View File

@@ -140,7 +140,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Ok(InferOk { value, obligations }) if self.next_trait_solver() => { Ok(InferOk { value, obligations }) if self.next_trait_solver() => {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
ocx.register_obligations(obligations); ocx.register_obligations(obligations);
if ocx.select_where_possible().is_empty() { if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { value, obligations: ocx.into_pending_obligations() }) Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
} else { } else {
Err(TypeError::Mismatch) Err(TypeError::Mismatch)
@@ -677,7 +677,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Some(ty::PredicateKind::AliasRelate(..)) => { Some(ty::PredicateKind::AliasRelate(..)) => {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch); return Err(TypeError::Mismatch);
} }
coercion.obligations.extend(ocx.into_pending_obligations()); coercion.obligations.extend(ocx.into_pending_obligations());
@@ -1099,7 +1099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false; return false;
}; };
ocx.register_obligations(ok.obligations); ocx.register_obligations(ok.obligations);
ocx.select_where_possible().is_empty() ocx.try_evaluate_obligations().is_empty()
}) })
} }
@@ -1203,7 +1203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.next_trait_solver() { if self.next_trait_solver() {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
let value = ocx.lub(cause, self.param_env, prev_ty, new_ty)?; let value = ocx.lub(cause, self.param_env, prev_ty, new_ty)?;
if ocx.select_where_possible().is_empty() { if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { Ok(InferOk {
value, value,
obligations: ocx.into_pending_obligations(), obligations: ocx.into_pending_obligations(),
@@ -1818,7 +1818,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
)) ))
}), }),
); );
ocx.select_where_possible().is_empty() ocx.try_evaluate_obligations().is_empty()
}) })
}; };

View File

@@ -2017,7 +2017,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.fudge_inference_if_ok(|| { self.fudge_inference_if_ok(|| {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?; ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?;
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch); return Err(TypeError::Mismatch);
} }
Ok(self.resolve_vars_if_possible(adt_ty)) Ok(self.resolve_vars_if_possible(adt_ty))
@@ -3663,7 +3663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
), ),
); );
let true_errors = ocx.select_where_possible(); let true_errors = ocx.try_evaluate_obligations();
// Do a leak check -- we can't really report a useful error here, // Do a leak check -- we can't really report a useful error here,
// but it at least avoids an ICE when the error has to do with higher-ranked // but it at least avoids an ICE when the error has to do with higher-ranked
@@ -3671,7 +3671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.leak_check(outer_universe, Some(snapshot))?; self.leak_check(outer_universe, Some(snapshot))?;
// Bail if we have ambiguity errors, which we can't report in a useful way. // Bail if we have ambiguity errors, which we can't report in a useful way.
let ambiguity_errors = ocx.select_all_or_error(); let ambiguity_errors = ocx.evaluate_obligations_error_on_ambiguity();
if true_errors.is_empty() && !ambiguity_errors.is_empty() { if true_errors.is_empty() && !ambiguity_errors.is_empty() {
return Err(NoSolution); return Err(NoSolution);
} }

View File

@@ -495,7 +495,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
.expect("expected diverging var to be unconstrained"); .expect("expected diverging var to be unconstrained");
} }
ocx.select_where_possible() ocx.try_evaluate_obligations()
}) })
}; };

View File

@@ -654,7 +654,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>), mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
) { ) {
let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); let mut result = self.fulfillment_cx.borrow_mut().try_evaluate_obligations(self);
if !result.is_empty() { if !result.is_empty() {
mutate_fulfillment_errors(&mut result); mutate_fulfillment_errors(&mut result);
self.adjust_fulfillment_errors_for_expr_obligation(&mut result); self.adjust_fulfillment_errors_for_expr_obligation(&mut result);

View File

@@ -255,7 +255,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// No argument expectations are produced if unification fails. // No argument expectations are produced if unification fails.
let origin = self.misc(call_span); let origin = self.misc(call_span);
ocx.sup(&origin, self.param_env, expected_output, formal_output)?; ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch); return Err(TypeError::Mismatch);
} }

View File

@@ -199,7 +199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
let normalized_fn_sig = let normalized_fn_sig =
ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig); ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig);
if ocx.select_all_or_error().is_empty() { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig); let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig);
if !normalized_fn_sig.has_infer() { if !normalized_fn_sig.has_infer() {
return normalized_fn_sig; return normalized_fn_sig;
@@ -347,7 +347,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
); );
ocx.register_obligations(impl_obligations); ocx.register_obligations(impl_obligations);
let mut errors = ocx.select_where_possible(); let mut errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
fulfillment_errors.append(&mut errors); fulfillment_errors.append(&mut errors);
return false; return false;

View File

@@ -1906,7 +1906,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// them to deal with defining uses in `method_autoderef_steps`. // them to deal with defining uses in `method_autoderef_steps`.
if self.next_trait_solver() { if self.next_trait_solver() {
ocx.register_obligations(instantiate_self_ty_obligations.iter().cloned()); ocx.register_obligations(instantiate_self_ty_obligations.iter().cloned());
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
unreachable!("unexpected autoderef error {errors:?}"); unreachable!("unexpected autoderef error {errors:?}");
} }
@@ -2103,7 +2103,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} }
// Evaluate those obligations to see if they might possibly hold. // Evaluate those obligations to see if they might possibly hold.
for error in ocx.select_where_possible() { for error in ocx.try_evaluate_obligations() {
result = ProbeResult::NoMatch; result = ProbeResult::NoMatch;
let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate); let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate);
if let Some(trait_predicate) = trait_predicate if let Some(trait_predicate) = trait_predicate
@@ -2143,7 +2143,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} }
// Evaluate those obligations to see if they might possibly hold. // Evaluate those obligations to see if they might possibly hold.
for error in ocx.select_where_possible() { for error in ocx.try_evaluate_obligations() {
result = ProbeResult::NoMatch; result = ProbeResult::NoMatch;
possibly_unsatisfied_predicates.push(( possibly_unsatisfied_predicates.push((
error.obligation.predicate, error.obligation.predicate,
@@ -2230,7 +2230,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}; };
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
let self_ty = ocx.register_infer_ok_obligations(ok); let self_ty = ocx.register_infer_ok_obligations(ok);
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
debug!("failed to prove instantiate self_ty obligations"); debug!("failed to prove instantiate self_ty obligations");
return false; return false;
} }

View File

@@ -1030,7 +1030,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx); let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
Err(ocx.select_all_or_error()) Err(ocx.evaluate_obligations_error_on_ambiguity())
} }
} }
} }

View File

@@ -125,7 +125,7 @@ impl<'tcx> InferCtxt<'tcx> {
T: Debug + TypeFoldable<TyCtxt<'tcx>>, T: Debug + TypeFoldable<TyCtxt<'tcx>>,
{ {
// Select everything, returning errors. // Select everything, returning errors.
let errors = fulfill_cx.select_all_or_error(self); let errors = fulfill_cx.evaluate_obligations_error_on_ambiguity(self);
// True error! // True error!
if errors.iter().any(|e| e.is_true_error()) { if errors.iter().any(|e| e.is_true_error()) {

View File

@@ -72,6 +72,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
self.register_predicate_obligation(infcx, obligation); self.register_predicate_obligation(infcx, obligation);
} }
} }
/// Go over the list of pending obligations and try to evaluate them. /// Go over the list of pending obligations and try to evaluate them.
/// ///
/// For each result: /// For each result:
@@ -81,7 +82,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
/// ///
/// Returns a list of errors from obligations that evaluated to Err. /// Returns a list of errors from obligations that evaluated to Err.
#[must_use] #[must_use]
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>; fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>; fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
@@ -94,8 +95,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
/// ///
/// Returns a list of errors from obligations that evaluated to Ambiguous or Err. /// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
#[must_use] #[must_use]
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> { fn evaluate_obligations_error_on_ambiguity(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let errors = self.select_where_possible(infcx); let errors = self.try_evaluate_obligations(infcx);
if !errors.is_empty() { if !errors.is_empty() {
return errors; return errors;
} }
@@ -108,7 +109,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
fn pending_obligations(&self) -> PredicateObligations<'tcx>; fn pending_obligations(&self) -> PredicateObligations<'tcx>;
/// Among all pending obligations, collect those are stalled on a inference variable which has /// Among all pending obligations, collect those are stalled on a inference variable which has
/// changed since the last call to `select_where_possible`. Those obligations are marked as /// changed since the last call to `try_evaluate_obligations`. Those obligations are marked as
/// successful and returned. /// successful and returned.
fn drain_stalled_obligations_for_coroutines( fn drain_stalled_obligations_for_coroutines(
&mut self, &mut self,

View File

@@ -180,5 +180,5 @@ fn suggest_question_mark<'tcx>(
into_iterator_did, into_iterator_did,
); );
ocx.select_all_or_error().is_empty() ocx.evaluate_obligations_error_on_ambiguity().is_empty()
} }

View File

@@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
let assoc_pred = let assoc_pred =
ocx.normalize(&traits::ObligationCause::dummy(), cx.param_env, assoc_pred); ocx.normalize(&traits::ObligationCause::dummy(), cx.param_env, assoc_pred);
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
// Can't normalize for some reason...? // Can't normalize for some reason...?
continue; continue;
} }
@@ -166,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// If that predicate doesn't hold modulo regions (but passed during type-check), // If that predicate doesn't hold modulo regions (but passed during type-check),
// then we must've taken advantage of the hack in `project_and_unify_types` where // then we must've taken advantage of the hack in `project_and_unify_types` where
// we replace opaques with inference vars. Emit a warning! // we replace opaques with inference vars. Emit a warning!
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
// If it's a trait bound and an opaque that doesn't satisfy it, // If it's a trait bound and an opaque that doesn't satisfy it,
// then we can emit a suggestion to add the bound. // then we can emit a suggestion to add the bound.
let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {

View File

@@ -1429,7 +1429,7 @@ fn check_field_tys_sized<'tcx>(
); );
} }
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
debug!(?errors); debug!(?errors);
if !errors.is_empty() { if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(errors); infcx.err_ctxt().report_fulfillment_errors(errors);

View File

@@ -623,7 +623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
param_env, param_env,
pred, pred,
)); ));
ocx.select_all_or_error().is_empty() ocx.evaluate_obligations_error_on_ambiguity().is_empty()
} }
} }

View File

@@ -2013,7 +2013,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let sig = ocx.normalize(&cause, param_env, sig); let sig = ocx.normalize(&cause, param_env, sig);
// proc macro is not WF. // proc macro is not WF.
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
return; return;
} }
@@ -2081,7 +2081,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.abort.set(true); self.abort.set(true);
} }
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(errors); infcx.err_ctxt().report_fulfillment_errors(errors);
self.abort.set(true); self.abort.set(true);

View File

@@ -56,7 +56,7 @@ pub fn ensure_wf<'tcx>(
pred, pred,
); );
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(errors); infcx.err_ctxt().report_fulfillment_errors(errors);
false false

View File

@@ -83,7 +83,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
}); });
ocx.register_obligations(obligations); ocx.register_obligations(obligations);
ocx.select_where_possible().is_empty() ocx.try_evaluate_obligations().is_empty()
}) })
}; };
@@ -113,7 +113,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
return false; return false;
} }
ocx.select_where_possible().is_empty() ocx.try_evaluate_obligations().is_empty()
}) })
}; };

View File

@@ -1470,7 +1470,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// //
// we intentionally drop errors from normalization here, // we intentionally drop errors from normalization here,
// since the normalization is just done to improve the error message. // since the normalization is just done to improve the error message.
let _ = ocx.select_where_possible(); let _ = ocx.try_evaluate_obligations();
if let Err(new_err) = if let Err(new_err) =
ocx.eq(&obligation.cause, obligation.param_env, data.term, normalized_term) ocx.eq(&obligation.cause, obligation.param_env, data.term, normalized_term)
@@ -2086,7 +2086,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
) )
}), }),
); );
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return false; return false;
} }
@@ -2102,7 +2102,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
{ {
terrs.push(terr); terrs.push(terr);
} }
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return false; return false;
} }
} }
@@ -3440,7 +3440,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
); );
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
if ocx.select_all_or_error().is_empty() { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return Ok(( return Ok((
self.tcx self.tcx
.fn_trait_kind_from_def_id(trait_def_id) .fn_trait_kind_from_def_id(trait_def_id)

View File

@@ -4590,7 +4590,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
param_env, param_env,
projection, projection,
)); ));
if ocx.select_where_possible().is_empty() if ocx.try_evaluate_obligations().is_empty()
&& let ty = self.resolve_vars_if_possible(ty) && let ty = self.resolve_vars_if_possible(ty)
&& !ty.is_ty_var() && !ty.is_ty_var()
{ {
@@ -4737,7 +4737,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pred, pred,
)); ));
}); });
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
// encountered errors. // encountered errors.
return; return;
} }

View File

@@ -25,7 +25,7 @@ impl<'tcx> InferCtxt<'tcx> {
let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, a, b) else { let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, a, b) else {
return false; return false;
}; };
ocx.select_where_possible().is_empty() ocx.try_evaluate_obligations().is_empty()
}) })
} }
@@ -124,7 +124,7 @@ impl<'tcx> InferCtxt<'tcx> {
param_env, param_env,
ty::TraitRef::new(self.tcx, trait_def_id, [ty]), ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
)); ));
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
// Find the original predicate in the list of predicates that could definitely not be fulfilled. // Find the original predicate in the list of predicates that could definitely not be fulfilled.
// If it is in that list, then we know this doesn't even shallowly implement the trait. // If it is in that list, then we know this doesn't even shallowly implement the trait.
// If it is not in that list, it was fulfilled, but there may be nested obligations, which we don't care about here. // If it is not in that list, it was fulfilled, but there may be nested obligations, which we don't care about here.

View File

@@ -60,7 +60,7 @@ struct ObligationStorage<'tcx> {
/// Obligations which resulted in an overflow in fulfillment itself. /// Obligations which resulted in an overflow in fulfillment itself.
/// ///
/// We cannot eagerly return these as error so we instead store them here /// We cannot eagerly return these as error so we instead store them here
/// to avoid recomputing them each time `select_where_possible` is called. /// to avoid recomputing them each time `try_evaluate_obligations` is called.
/// This also allows us to return the correct `FulfillmentError` for them. /// This also allows us to return the correct `FulfillmentError` for them.
overflowed: Vec<PredicateObligation<'tcx>>, overflowed: Vec<PredicateObligation<'tcx>>,
pending: PendingObligations<'tcx>, pending: PendingObligations<'tcx>,
@@ -101,7 +101,7 @@ impl<'tcx> ObligationStorage<'tcx> {
// IMPORTANT: we must not use solve any inference variables in the obligations // IMPORTANT: we must not use solve any inference variables in the obligations
// as this is all happening inside of a probe. We use a probe to make sure // as this is all happening inside of a probe. We use a probe to make sure
// we get all obligations involved in the overflow. We pretty much check: if // we get all obligations involved in the overflow. We pretty much check: if
// we were to do another step of `select_where_possible`, which goals would // we were to do another step of `try_evaluate_obligations`, which goals would
// change. // change.
// FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed. // FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
self.overflowed.extend( self.overflowed.extend(
@@ -179,7 +179,7 @@ where
.collect() .collect()
} }
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> { fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
let mut errors = Vec::new(); let mut errors = Vec::new();
loop { loop {

View File

@@ -76,7 +76,7 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
self.unconstrained_term, self.unconstrained_term,
)?; )?;
f(&ocx); f(&ocx);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.is_empty() { if errors.is_empty() {
Ok(Certainty::Yes) Ok(Certainty::Yes)
} else if errors.iter().all(|e| !e.is_true_error()) { } else if errors.iter().all(|e| !e.is_true_error()) {

View File

@@ -79,7 +79,7 @@ where
stalled_coroutine_goals: vec![], stalled_coroutine_goals: vec![],
}; };
let value = value.try_fold_with(&mut folder)?; let value = value.try_fold_with(&mut folder)?;
let errors = folder.fulfill_cx.select_all_or_error(at.infcx); let errors = folder.fulfill_cx.evaluate_obligations_error_on_ambiguity(at.infcx);
if errors.is_empty() { Ok((value, folder.stalled_coroutine_goals)) } else { Err(errors) } if errors.is_empty() { Ok((value, folder.stalled_coroutine_goals)) } else { Err(errors) }
} }
@@ -128,7 +128,7 @@ where
); );
self.fulfill_cx.register_predicate_obligation(infcx, obligation); self.fulfill_cx.register_predicate_obligation(infcx, obligation);
self.select_all_and_stall_coroutine_predicates()?; self.evaluate_all_error_on_ambiguity_stall_coroutine_predicates()?;
// Alias is guaranteed to be fully structurally resolved, // Alias is guaranteed to be fully structurally resolved,
// so we can super fold here. // so we can super fold here.
@@ -143,8 +143,8 @@ where
Ok(result) Ok(result)
} }
fn select_all_and_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> { fn evaluate_all_error_on_ambiguity_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> {
let errors = self.fulfill_cx.select_where_possible(self.at.infcx); let errors = self.fulfill_cx.try_evaluate_obligations(self.at.infcx);
if !errors.is_empty() { if !errors.is_empty() {
return Err(errors); return Err(errors);
} }

View File

@@ -155,7 +155,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
// an additional sanity check. // an additional sanity check.
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
ocx.register_bound(ObligationCause::dummy(), full_env, ty, trait_did); ocx.register_bound(ObligationCause::dummy(), full_env, ty, trait_did);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
panic!("Unable to fulfill trait {trait_did:?} for '{ty:?}': {errors:?}"); panic!("Unable to fulfill trait {trait_did:?} for '{ty:?}': {errors:?}");
} }

View File

@@ -371,7 +371,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
ocx.register_obligations(obligations.iter().cloned()); ocx.register_obligations(obligations.iter().cloned());
let hard_errors = ocx.select_where_possible(); let hard_errors = ocx.try_evaluate_obligations();
if !hard_errors.is_empty() { if !hard_errors.is_empty() {
assert!( assert!(
hard_errors.iter().all(|e| e.is_true_error()), hard_errors.iter().all(|e| e.is_true_error()),
@@ -386,7 +386,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
let ambiguities = ocx.into_pending_obligations(); let ambiguities = ocx.into_pending_obligations();
let ocx = ObligationCtxt::new_with_diagnostics(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
ocx.register_obligations(ambiguities); ocx.register_obligations(ambiguities);
let errors_and_ambiguities = ocx.select_all_or_error(); let errors_and_ambiguities = ocx.evaluate_obligations_error_on_ambiguity();
// We only care about the obligations that are *definitely* true errors. // We only care about the obligations that are *definitely* true errors.
// Ambiguities do not prove the disjointness of two impls. // Ambiguities do not prove the disjointness of two impls.
let (errors, ambiguities): (Vec<_>, Vec<_>) = let (errors, ambiguities): (Vec<_>, Vec<_>) =
@@ -623,7 +623,7 @@ fn try_prove_negated_where_clause<'tcx>(
param_env, param_env,
negative_predicate, negative_predicate,
)); ));
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return false; return false;
} }
@@ -743,7 +743,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
ty = ocx ty = ocx
.structurally_normalize_ty(&ObligationCause::dummy(), param_env, ty) .structurally_normalize_ty(&ObligationCause::dummy(), param_env, ty)
.map_err(|_| ())?; .map_err(|_| ())?;
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return Err(()); return Err(());
} }
} }

View File

@@ -176,7 +176,7 @@ fn satisfied_from_param_env<'tcx>(
if self.infcx.probe(|_| { if self.infcx.probe(|_| {
let ocx = ObligationCtxt::new(self.infcx); let ocx = ObligationCtxt::new(self.infcx);
ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok() ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
&& ocx.select_all_or_error().is_empty() && ocx.evaluate_obligations_error_on_ambiguity().is_empty()
}) { }) {
self.single_match = match self.single_match { self.single_match = match self.single_match {
None => Some(Ok(c)), None => Some(Ok(c)),
@@ -217,7 +217,7 @@ fn satisfied_from_param_env<'tcx>(
if let Some(Ok(c)) = single_match { if let Some(Ok(c)) = single_match {
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok()); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty()); assert!(ocx.evaluate_obligations_error_on_ambiguity().is_empty());
return true; return true;
} }

View File

@@ -202,14 +202,30 @@ where
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
} }
/// Go over the list of pending obligations and try to evaluate them.
///
/// For each result:
/// Ok: remove the obligation from the list
/// Ambiguous: leave the obligation in the list to be evaluated later
/// Err: remove the obligation from the list and return an error
///
/// Returns a list of errors from obligations that evaluated to Err.
#[must_use] #[must_use]
pub fn select_where_possible(&self) -> Vec<E> { pub fn try_evaluate_obligations(&self) -> Vec<E> {
self.engine.borrow_mut().select_where_possible(self.infcx) self.engine.borrow_mut().try_evaluate_obligations(self.infcx)
} }
/// Evaluate all pending obligations, return error if they can't be evaluated.
///
/// For each result:
/// Ok: remove the obligation from the list
/// Ambiguous: remove the obligation from the list and return an error
/// Err: remove the obligation from the list and return an error
///
/// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
#[must_use] #[must_use]
pub fn select_all_or_error(&self) -> Vec<E> { pub fn evaluate_obligations_error_on_ambiguity(&self) -> Vec<E> {
self.engine.borrow_mut().select_all_or_error(self.infcx) self.engine.borrow_mut().evaluate_obligations_error_on_ambiguity(self.infcx)
} }
/// Returns the not-yet-processed and stalled obligations from the /// Returns the not-yet-processed and stalled obligations from the

View File

@@ -52,11 +52,11 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
/// consists of a list of obligations that must be (eventually) /// consists of a list of obligations that must be (eventually)
/// satisfied. The job is to track which are satisfied, which yielded /// satisfied. The job is to track which are satisfied, which yielded
/// errors, and which are still pending. At any point, users can call /// errors, and which are still pending. At any point, users can call
/// `select_where_possible`, and the fulfillment context will try to do /// `try_evaluate_obligations`, and the fulfillment context will try to do
/// selection, retaining only those obligations that remain /// selection, retaining only those obligations that remain
/// ambiguous. This may be helpful in pushing type inference /// ambiguous. This may be helpful in pushing type inference
/// along. Once all type inference constraints have been generated, the /// along. Once all type inference constraints have been generated, the
/// method `select_all_or_error` can be used to report any remaining /// method `evaluate_obligations_error_on_ambiguity` can be used to report any remaining
/// ambiguous cases as errors. /// ambiguous cases as errors.
pub struct FulfillmentContext<'tcx, E: 'tcx> { pub struct FulfillmentContext<'tcx, E: 'tcx> {
/// A list of all obligations that have been registered with this /// A list of all obligations that have been registered with this
@@ -163,7 +163,7 @@ where
.collect() .collect()
} }
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> { fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let selcx = SelectionContext::new(infcx); let selcx = SelectionContext::new(infcx);
self.select(selcx) self.select(selcx)
} }

View File

@@ -156,7 +156,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
ty::ClauseKind::UnstableFeature(sym::unsized_const_params), ty::ClauseKind::UnstableFeature(sym::unsized_const_params),
)); ));
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired); return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
} }
} }
@@ -168,7 +168,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
tcx.require_lang_item(LangItem::ConstParamTy, parent_cause.span), tcx.require_lang_item(LangItem::ConstParamTy, parent_cause.span),
); );
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Fulfill(errors))); infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Fulfill(errors)));
continue; continue;
@@ -235,7 +235,7 @@ pub fn all_fields_implement_trait<'tcx>(
ObligationCause::dummy_with_span(field_ty_span) ObligationCause::dummy_with_span(field_ty_span)
}; };
let ty = ocx.normalize(&normalization_cause, param_env, unnormalized_ty); let ty = ocx.normalize(&normalization_cause, param_env, unnormalized_ty);
let normalization_errors = ocx.select_where_possible(); let normalization_errors = ocx.try_evaluate_obligations();
// NOTE: The post-normalization type may also reference errors, // NOTE: The post-normalization type may also reference errors,
// such as when we project to a missing type or we have a mismatch // such as when we project to a missing type or we have a mismatch
@@ -252,7 +252,7 @@ pub fn all_fields_implement_trait<'tcx>(
ty, ty,
trait_def_id, trait_def_id,
); );
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
infringing.push((field, ty, InfringingFieldsReason::Fulfill(errors))); infringing.push((field, ty, InfringingFieldsReason::Fulfill(errors)));
} }

View File

@@ -231,7 +231,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
match errors.as_slice() { match errors.as_slice() {
// Only known to hold if we did no inference. // Only known to hold if we did no inference.
[] => infcx.resolve_vars_if_possible(goal) == goal, [] => infcx.resolve_vars_if_possible(goal) == goal,
@@ -273,7 +273,7 @@ fn do_normalize_predicates<'tcx>(
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let predicates = ocx.normalize(&cause, elaborated_env, predicates); let predicates = ocx.normalize(&cause, elaborated_env, predicates);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors); let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported); return Err(reported);
@@ -738,13 +738,13 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
} }
// Use `select_where_possible` to only return impossible for true errors, // Use `try_evaluate_obligations` to only return impossible for true errors,
// and not ambiguities or overflows. Since the new trait solver forces // and not ambiguities or overflows. Since the new trait solver forces
// some currently undetected overlap between `dyn Trait: Trait` built-in // some currently undetected overlap between `dyn Trait: Trait` built-in
// vs user-written impls to AMBIGUOUS, this may return ambiguity even // vs user-written impls to AMBIGUOUS, this may return ambiguity even
// with no infer vars. There may also be ways to encounter ambiguity due // with no infer vars. There may also be ways to encounter ambiguity due
// to post-mono overflow. // to post-mono overflow.
let true_errors = ocx.select_where_possible(); let true_errors = ocx.try_evaluate_obligations();
if !true_errors.is_empty() { if !true_errors.is_empty() {
return true; return true;
} }
@@ -853,7 +853,7 @@ fn is_impossible_associated_item(
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligations(predicates_for_trait); ocx.register_obligations(predicates_for_trait);
!ocx.select_where_possible().is_empty() !ocx.try_evaluate_obligations().is_empty()
} }
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {

View File

@@ -73,7 +73,7 @@ impl<'tcx> At<'_, 'tcx> {
let value = self let value = self
.normalize(value) .normalize(value)
.into_value_registering_obligations(self.infcx, &mut *fulfill_cx); .into_value_registering_obligations(self.infcx, &mut *fulfill_cx);
let errors = fulfill_cx.select_all_or_error(self.infcx); let errors = fulfill_cx.evaluate_obligations_error_on_ambiguity(self.infcx);
let value = self.infcx.resolve_vars_if_possible(value); let value = self.infcx.resolve_vars_if_possible(value);
if errors.is_empty() { if errors.is_empty() {
Ok(value) Ok(value)

View File

@@ -199,7 +199,7 @@ where
// Flush errors b/c `deeply_normalize` doesn't expect pending // Flush errors b/c `deeply_normalize` doesn't expect pending
// obligations, and we may have pending obligations from the // obligations, and we may have pending obligations from the
// branch above (from other types). // branch above (from other types).
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
return Err(errors); return Err(errors);
} }

View File

@@ -96,7 +96,7 @@ impl<'tcx> InferCtxt<'tcx> {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation.clone()); ocx.register_obligation(obligation.clone());
let mut result = EvaluationResult::EvaluatedToOk; let mut result = EvaluationResult::EvaluatedToOk;
for error in ocx.select_all_or_error() { for error in ocx.evaluate_obligations_error_on_ambiguity() {
if error.is_true_error() { if error.is_true_error() {
return Ok(EvaluationResult::EvaluatedToErr); return Ok(EvaluationResult::EvaluatedToErr);
} else { } else {

View File

@@ -94,7 +94,7 @@ where
let value = op(&ocx).map_err(|_| { let value = op(&ocx).map_err(|_| {
infcx.dcx().span_delayed_bug(span, format!("error performing operation: {name}")) infcx.dcx().span_delayed_bug(span, format!("error performing operation: {name}"))
})?; })?;
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.is_empty() { if errors.is_empty() {
Ok(value) Ok(value)
} else if let Err(guar) = infcx.tcx.check_potentially_region_dependent_goals(root_def_id) { } else if let Err(guar) = infcx.tcx.check_potentially_region_dependent_goals(root_def_id) {

View File

@@ -164,7 +164,7 @@ fn fulfill_implication<'tcx>(
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
let source_trait_ref = ocx.normalize(cause, param_env, source_trait_ref); let source_trait_ref = ocx.normalize(cause, param_env, source_trait_ref);
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
infcx.dcx().span_delayed_bug( infcx.dcx().span_delayed_bug(
infcx.tcx.def_span(source_impl), infcx.tcx.def_span(source_impl),
format!("failed to fully normalize {source_trait_ref}"), format!("failed to fully normalize {source_trait_ref}"),
@@ -197,7 +197,7 @@ fn fulfill_implication<'tcx>(
let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates); let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates);
ocx.register_obligations(obligations); ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
// no dice! // no dice!
debug!( debug!(
@@ -295,7 +295,7 @@ pub(super) fn specializes(
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let specializing_impl_trait_ref = ocx.normalize(cause, param_env, specializing_impl_trait_ref); let specializing_impl_trait_ref = ocx.normalize(cause, param_env, specializing_impl_trait_ref);
if !ocx.select_all_or_error().is_empty() { if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
infcx.dcx().span_delayed_bug( infcx.dcx().span_delayed_bug(
infcx.tcx.def_span(specializing_impl_def_id), infcx.tcx.def_span(specializing_impl_def_id),
format!("failed to fully normalize {specializing_impl_trait_ref}"), format!("failed to fully normalize {specializing_impl_trait_ref}"),
@@ -331,7 +331,7 @@ pub(super) fn specializes(
let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates); let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates);
ocx.register_obligations(obligations); ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
// no dice! // no dice!
debug!( debug!(
@@ -367,7 +367,7 @@ pub(super) fn specializes(
) )
})); }));
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
// no dice! // no dice!
debug!( debug!(

View File

@@ -52,7 +52,7 @@ impl<'tcx> At<'_, 'tcx> {
); );
fulfill_cx.register_predicate_obligation(self.infcx, obligation); fulfill_cx.register_predicate_obligation(self.infcx, obligation);
let errors = fulfill_cx.select_where_possible(self.infcx); let errors = fulfill_cx.try_evaluate_obligations(self.infcx);
if !errors.is_empty() { if !errors.is_empty() {
return Err(errors); return Err(errors);
} }

View File

@@ -59,7 +59,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
// In principle, we only need to do this so long as `impl_source` // In principle, we only need to do this so long as `impl_source`
// contains unbound type parameters. It could be a slight // contains unbound type parameters. It could be a slight
// optimization to stop iterating early. // optimization to stop iterating early.
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() { if !errors.is_empty() {
// `rustc_monomorphize::collector` assumes there are no type errors. // `rustc_monomorphize::collector` assumes there are no type errors.
// Cycle errors are the only post-monomorphization errors possible; emit them now so // Cycle errors are the only post-monomorphization errors possible; emit them now so

View File

@@ -63,7 +63,7 @@ fn compute_assumptions<'tcx>(
ty::ClauseKind::WellFormed(ty.into()), ty::ClauseKind::WellFormed(ty.into()),
) )
})); }));
let _errors = ocx.select_all_or_error(); let _errors = ocx.evaluate_obligations_error_on_ambiguity();
let region_obligations = infcx.take_registered_region_obligations(); let region_obligations = infcx.take_registered_region_obligations();
let region_assumptions = infcx.take_registered_region_assumptions(); let region_assumptions = infcx.take_registered_region_assumptions();

View File

@@ -45,7 +45,7 @@ fn normalize_canonicalized_projection_ty<'tcx>(
// are recursive (given some generic parameters of the opaque's type variables). // are recursive (given some generic parameters of the opaque's type variables).
// In that case, we may only realize a cycle error when calling // In that case, we may only realize a cycle error when calling
// `normalize_erasing_regions` in mono. // `normalize_erasing_regions` in mono.
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
// Rustdoc may attempt to normalize type alias types which are not // Rustdoc may attempt to normalize type alias types which are not
// well-formed. Rustdoc also normalizes types that are just not // well-formed. Rustdoc also normalizes types that are just not

View File

@@ -28,7 +28,7 @@ fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
// //
// 2. We are sometimes doing future-incompatibility lints for // 2. We are sometimes doing future-incompatibility lints for
// now, so we do not want unconditional errors here. // now, so we do not want unconditional errors here.
ocx.select_all_or_error().is_empty() ocx.evaluate_obligations_error_on_ambiguity().is_empty()
} }
pub(crate) fn provide(providers: &mut Providers) { pub(crate) fn provide(providers: &mut Providers) {

View File

@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let cause = traits::ObligationCause::misc(span, fn_def_id); let cause = traits::ObligationCause::misc(span, fn_def_id);
ocx.register_bound(cause, cx.param_env, ret_ty, send_trait); ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
let send_errors = ocx.select_all_or_error(); let send_errors = ocx.evaluate_obligations_error_on_ambiguity();
// Allow errors that try to prove `Send` for types that "mention" a generic parameter at the "top // Allow errors that try to prove `Send` for types that "mention" a generic parameter at the "top
// level". // level".

View File

@@ -475,7 +475,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligations(impl_src.nested_obligations()); ocx.register_obligations(impl_src.nested_obligations());
ocx.select_all_or_error().is_empty() ocx.evaluate_obligations_error_on_ambiguity().is_empty()
} }
!ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env) !ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env)

View File

@@ -304,7 +304,7 @@ fn structurally_normalize_ty<'db>(
// evaluate/fulfill mismatches, but that's not a reason for an ICE. // evaluate/fulfill mismatches, but that's not a reason for an ICE.
return None; return None;
}; };
let errors = ocx.select_where_possible(); let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() { if !errors.is_empty() {
unreachable!(); unreachable!();
} }

View File

@@ -160,7 +160,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
Ok(InferOk { value, obligations }) => { Ok(InferOk { value, obligations }) => {
let mut ocx = ObligationCtxt::new(this.infer_ctxt()); let mut ocx = ObligationCtxt::new(this.infer_ctxt());
ocx.register_obligations(obligations); ocx.register_obligations(obligations);
if ocx.select_where_possible().is_empty() { if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { value, obligations: ocx.into_pending_obligations() }) Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
} else { } else {
Err(TypeError::Mismatch) Err(TypeError::Mismatch)
@@ -743,7 +743,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
Some(PredicateKind::AliasRelate(..)) => { Some(PredicateKind::AliasRelate(..)) => {
let mut ocx = ObligationCtxt::new(self.infer_ctxt()); let mut ocx = ObligationCtxt::new(self.infer_ctxt());
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch); return Err(TypeError::Mismatch);
} }
coercion.obligations.extend(ocx.into_pending_obligations()); coercion.obligations.extend(ocx.into_pending_obligations());
@@ -1119,7 +1119,7 @@ impl<'db> InferenceContext<'db> {
prev_ty, prev_ty,
new_ty, new_ty,
)?; )?;
if ocx.select_where_possible().is_empty() { if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { value, obligations: ocx.into_pending_obligations() }) Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
} else { } else {
Err(TypeError::Mismatch) Err(TypeError::Mismatch)

View File

@@ -2151,7 +2151,7 @@ impl<'db> InferenceContext<'db> {
expected_output.to_nextsolver(interner), expected_output.to_nextsolver(interner),
formal_output, formal_output,
)?; )?;
if !ocx.select_where_possible().is_empty() { if !ocx.try_evaluate_obligations().is_empty() {
return Err(crate::next_solver::TypeError::Mismatch); return Err(crate::next_solver::TypeError::Mismatch);
} }

View File

@@ -818,7 +818,7 @@ impl<'db> InferenceTable<'db> {
} }
pub(crate) fn select_obligations_where_possible(&mut self) { pub(crate) fn select_obligations_where_possible(&mut self) {
self.fulfillment_cx.select_where_possible(&self.infer_ctxt); self.fulfillment_cx.try_evaluate_obligations(&self.infer_ctxt);
} }
pub(super) fn register_predicate( pub(super) fn register_predicate(

View File

@@ -1785,7 +1785,7 @@ fn is_valid_trait_method_candidate(
let mut ctxt = ObligationCtxt::new(&table.infer_ctxt); let mut ctxt = ObligationCtxt::new(&table.infer_ctxt);
ctxt.register_obligations(infer_ok.into_obligations()); ctxt.register_obligations(infer_ok.into_obligations());
// FIXME: Are we doing this correctly? Probably better to follow rustc more closely. // FIXME: Are we doing this correctly? Probably better to follow rustc more closely.
check_that!(ctxt.select_where_possible().is_empty()); check_that!(ctxt.try_evaluate_obligations().is_empty());
} }
check_that!(table.unify(receiver_ty, &expected_receiver)); check_that!(table.unify(receiver_ty, &expected_receiver));
@@ -1871,7 +1871,7 @@ fn is_valid_impl_fn_candidate(
) )
})); }));
if ctxt.select_where_possible().is_empty() { if ctxt.try_evaluate_obligations().is_empty() {
IsValidCandidate::Yes IsValidCandidate::Yes
} else { } else {
IsValidCandidate::No IsValidCandidate::No

View File

@@ -54,7 +54,7 @@ struct ObligationStorage<'db> {
/// Obligations which resulted in an overflow in fulfillment itself. /// Obligations which resulted in an overflow in fulfillment itself.
/// ///
/// We cannot eagerly return these as error so we instead store them here /// We cannot eagerly return these as error so we instead store them here
/// to avoid recomputing them each time `select_where_possible` is called. /// to avoid recomputing them each time `try_evaluate_obligations` is called.
/// This also allows us to return the correct `FulfillmentError` for them. /// This also allows us to return the correct `FulfillmentError` for them.
overflowed: Vec<PredicateObligation<'db>>, overflowed: Vec<PredicateObligation<'db>>,
pending: PendingObligations<'db>, pending: PendingObligations<'db>,
@@ -95,7 +95,7 @@ impl<'db> ObligationStorage<'db> {
// IMPORTANT: we must not use solve any inference variables in the obligations // IMPORTANT: we must not use solve any inference variables in the obligations
// as this is all happening inside of a probe. We use a probe to make sure // as this is all happening inside of a probe. We use a probe to make sure
// we get all obligations involved in the overflow. We pretty much check: if // we get all obligations involved in the overflow. We pretty much check: if
// we were to do another step of `select_where_possible`, which goals would // we were to do another step of `try_evaluate_obligations`, which goals would
// change. // change.
// FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed. // FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
self.overflowed.extend( self.overflowed.extend(
@@ -131,7 +131,7 @@ impl<'db> FulfillmentCtxt<'db> {
infcx: &InferCtxt<'db>, infcx: &InferCtxt<'db>,
obligation: PredicateObligation<'db>, obligation: PredicateObligation<'db>,
) { ) {
// FIXME: See the comment in `select_where_possible()`. // FIXME: See the comment in `try_evaluate_obligations()`.
// assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); // assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
self.obligations.register(obligation, None); self.obligations.register(obligation, None);
} }
@@ -141,7 +141,7 @@ impl<'db> FulfillmentCtxt<'db> {
infcx: &InferCtxt<'db>, infcx: &InferCtxt<'db>,
obligations: impl IntoIterator<Item = PredicateObligation<'db>>, obligations: impl IntoIterator<Item = PredicateObligation<'db>>,
) { ) {
// FIXME: See the comment in `select_where_possible()`. // FIXME: See the comment in `try_evaluate_obligations()`.
// assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); // assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
obligations.into_iter().for_each(|obligation| self.obligations.register(obligation, None)); obligations.into_iter().for_each(|obligation| self.obligations.register(obligation, None));
} }
@@ -158,7 +158,7 @@ impl<'db> FulfillmentCtxt<'db> {
.collect() .collect()
} }
pub(crate) fn select_where_possible( pub(crate) fn try_evaluate_obligations(
&mut self, &mut self,
infcx: &InferCtxt<'db>, infcx: &InferCtxt<'db>,
) -> Vec<NextSolverError<'db>> { ) -> Vec<NextSolverError<'db>> {
@@ -223,11 +223,11 @@ impl<'db> FulfillmentCtxt<'db> {
errors errors
} }
pub(crate) fn select_all_or_error( pub(crate) fn evaluate_obligations_error_on_ambiguity(
&mut self, &mut self,
infcx: &InferCtxt<'db>, infcx: &InferCtxt<'db>,
) -> Vec<NextSolverError<'db>> { ) -> Vec<NextSolverError<'db>> {
let errors = self.select_where_possible(infcx); let errors = self.try_evaluate_obligations(infcx);
if !errors.is_empty() { if !errors.is_empty() {
return errors; return errors;
} }

View File

@@ -92,7 +92,7 @@ impl<'db> NormalizesToTermHack<'db> {
let mut ocx = ObligationCtxt::new(infcx); let mut ocx = ObligationCtxt::new(infcx);
ocx.eq(&ObligationCause::dummy(), param_env, self.term, self.unconstrained_term)?; ocx.eq(&ObligationCause::dummy(), param_env, self.term, self.unconstrained_term)?;
f(&mut ocx); f(&mut ocx);
let errors = ocx.select_all_or_error(); let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.is_empty() { if errors.is_empty() {
Ok(Certainty::Yes) Ok(Certainty::Yes)
} else if errors.iter().all(|e| !matches!(e, NextSolverError::TrueError(_))) { } else if errors.iter().all(|e| !matches!(e, NextSolverError::TrueError(_))) {

View File

@@ -77,7 +77,7 @@ where
stalled_coroutine_goals: vec![], stalled_coroutine_goals: vec![],
}; };
let value = value.try_fold_with(&mut folder)?; let value = value.try_fold_with(&mut folder)?;
let errors = folder.fulfill_cx.select_all_or_error(at.infcx); let errors = folder.fulfill_cx.evaluate_obligations_error_on_ambiguity(at.infcx);
if errors.is_empty() { Ok((value, folder.stalled_coroutine_goals)) } else { Err(errors) } if errors.is_empty() { Ok((value, folder.stalled_coroutine_goals)) } else { Err(errors) }
} }
@@ -138,7 +138,7 @@ impl<'db> NormalizationFolder<'_, 'db> {
fn select_all_and_stall_coroutine_predicates( fn select_all_and_stall_coroutine_predicates(
&mut self, &mut self,
) -> Result<(), Vec<NextSolverError<'db>>> { ) -> Result<(), Vec<NextSolverError<'db>>> {
let errors = self.fulfill_cx.select_where_possible(self.at.infcx); let errors = self.fulfill_cx.try_evaluate_obligations(self.at.infcx);
if !errors.is_empty() { if !errors.is_empty() {
return Err(errors); return Err(errors);
} }

View File

@@ -144,13 +144,13 @@ impl<'a, 'db> ObligationCtxt<'a, 'db> {
} }
#[must_use] #[must_use]
pub fn select_where_possible(&mut self) -> Vec<NextSolverError<'db>> { pub fn try_evaluate_obligations(&mut self) -> Vec<NextSolverError<'db>> {
self.engine.select_where_possible(self.infcx) self.engine.try_evaluate_obligations(self.infcx)
} }
#[must_use] #[must_use]
pub fn select_all_or_error(&mut self) -> Vec<NextSolverError<'db>> { pub fn evaluate_obligations_error_on_ambiguity(&mut self) -> Vec<NextSolverError<'db>> {
self.engine.select_all_or_error(self.infcx) self.engine.evaluate_obligations_error_on_ambiguity(self.infcx)
} }
/// Returns the not-yet-processed and stalled obligations from the /// Returns the not-yet-processed and stalled obligations from the

View File

@@ -47,7 +47,7 @@ impl<'db> At<'_, 'db> {
); );
fulfill_cx.register_predicate_obligation(self.infcx, obligation); fulfill_cx.register_predicate_obligation(self.infcx, obligation);
let errors = fulfill_cx.select_where_possible(self.infcx); let errors = fulfill_cx.try_evaluate_obligations(self.infcx);
if !errors.is_empty() { if !errors.is_empty() {
return Err(errors); return Err(errors);
} }

View File

@@ -13,7 +13,7 @@ fn foo() -> impl Default + Copy {
// Make a tuple `(?x, ?y)` and equate it with `(impl Default, u32)`. // Make a tuple `(?x, ?y)` and equate it with `(impl Default, u32)`.
// For us to try and prove a `Subtype(impl Default, u32)` obligation, // For us to try and prove a `Subtype(impl Default, u32)` obligation,
// we have to instantiate both `?x` and `?y` without any // we have to instantiate both `?x` and `?y` without any
// `select_where_possible` calls inbetween. // `try_evaluate_obligations` calls inbetween.
let mut tup = &mut (x, y); let mut tup = &mut (x, y);
let assign_tup = &mut (foo(), 1u32); let assign_tup = &mut (foo(), 1u32);
tup = assign_tup; tup = assign_tup;