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
// already run, but there's no point using `span_delayed_bug`
// 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());
try_extract_error_from_region_constraints(
ocx.infcx,

View File

@@ -1313,7 +1313,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
let cause = ObligationCause::misc(expr.span, self.mir_def_id());
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| {
match error.obligation.predicate.as_clause().and_then(|c| c.as_trait_clause()) {
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());
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
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)
}));
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(
tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(),
fluent::borrowck_dereference_suggestion,

View File

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

View File

@@ -139,7 +139,7 @@ pub fn validate_trivial_unsize<'tcx>(
) else {
return false;
};
if !ocx.select_all_or_error().is_empty() {
if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return false;
}
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() {
Some(ConstConditionsHold::Yes)
} else {

View File

@@ -119,7 +119,7 @@ impl Qualif for HasMutInterior {
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
!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 {

View File

@@ -43,5 +43,5 @@ pub fn relate_types<'tcx>(
Ok(()) => {}
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.
return None;
};
let errors = ocx.select_where_possible();
let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
if self.infcx.next_trait_solver() {
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`
// 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() {
let mut guar = None;
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
// version.
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(guar);
@@ -2028,7 +2028,7 @@ pub(super) fn check_coroutine_obligations(
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);
if !errors.is_empty() {
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));
}
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
debug!(?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
// version.
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
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
// RPITs.
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
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;
};
let errors = ocx.select_where_possible();
let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
return None;
}
@@ -2106,7 +2106,7 @@ fn compare_const_predicate_entailment<'tcx>(
// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
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
// version.
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
@@ -2367,7 +2367,7 @@ pub(super) fn check_type_bounds<'tcx>(
// Check that all obligations are satisfied by the implementation's
// version.
ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);

View File

@@ -164,7 +164,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
param_env,
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)");
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 norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
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() {
infcx.err_ctxt().report_fulfillment_errors(errors);
error = true;

View File

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

View File

@@ -142,7 +142,7 @@ where
}
f(&mut wfcx)?;
let errors = wfcx.select_all_or_error();
let errors = wfcx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
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(|_| {
let ocx = ObligationCtxt::new(wfcx.infcx);
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(());
}
@@ -1838,7 +1842,11 @@ fn receiver_is_valid<'tcx>(
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
let ocx = ObligationCtxt::new(wfcx.infcx);
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());
return Ok(());

View File

@@ -333,7 +333,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
param_env,
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 is_from_coerce_pointee_derive(tcx, span) {
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]),
);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
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 ty = ocx.normalize(&cause, ty::ParamEnv::empty(), user_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() {
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),
);
// 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 Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
&& 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())),
));
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);
if error.obligation.predicate == self.predicate {
// 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),
);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(guar);

View File

@@ -140,7 +140,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Ok(InferOk { value, obligations }) if self.next_trait_solver() => {
let ocx = ObligationCtxt::new(self);
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() })
} else {
Err(TypeError::Mismatch)
@@ -677,7 +677,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Some(ty::PredicateKind::AliasRelate(..)) => {
let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation);
if !ocx.select_where_possible().is_empty() {
if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch);
}
coercion.obligations.extend(ocx.into_pending_obligations());
@@ -1099,7 +1099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
};
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() {
let ocx = ObligationCtxt::new(self);
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 {
value,
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(|| {
let ocx = ObligationCtxt::new(self);
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);
}
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,
// 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))?;
// 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() {
return Err(NoSolution);
}

View File

@@ -495,7 +495,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
.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,
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() {
mutate_fulfillment_errors(&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.
let origin = self.misc(call_span);
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);
}

View File

@@ -199,7 +199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ocx = ObligationCtxt::new(self);
let normalized_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);
if !normalized_fn_sig.has_infer() {
return normalized_fn_sig;
@@ -347,7 +347,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
);
ocx.register_obligations(impl_obligations);
let mut errors = ocx.select_where_possible();
let mut errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
fulfillment_errors.append(&mut errors);
return false;

View File

@@ -1906,7 +1906,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// them to deal with defining uses in `method_autoderef_steps`.
if self.next_trait_solver() {
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() {
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.
for error in ocx.select_where_possible() {
for error in ocx.try_evaluate_obligations() {
result = ProbeResult::NoMatch;
let nested_predicate = self.resolve_vars_if_possible(error.obligation.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.
for error in ocx.select_where_possible() {
for error in ocx.try_evaluate_obligations() {
result = ProbeResult::NoMatch;
possibly_unsatisfied_predicates.push((
error.obligation.predicate,
@@ -2230,7 +2230,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
};
let ocx = ObligationCtxt::new(self);
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");
return false;
}

View File

@@ -1030,7 +1030,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
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>>,
{
// 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!
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);
}
}
/// Go over the list of pending obligations and try to evaluate them.
///
/// 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.
#[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>;
@@ -94,8 +95,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
///
/// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
#[must_use]
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let errors = self.select_where_possible(infcx);
fn evaluate_obligations_error_on_ambiguity(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let errors = self.try_evaluate_obligations(infcx);
if !errors.is_empty() {
return errors;
}
@@ -108,7 +109,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
fn pending_obligations(&self) -> PredicateObligations<'tcx>;
/// 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.
fn drain_stalled_obligations_for_coroutines(
&mut self,

View File

@@ -180,5 +180,5 @@ fn suggest_question_mark<'tcx>(
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 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...?
continue;
}
@@ -166,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// 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
// 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,
// then we can emit a suggestion to add the bound.
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);
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(errors);

View File

@@ -623,7 +623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
param_env,
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);
// proc macro is not WF.
let errors = ocx.select_where_possible();
let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
return;
}
@@ -2081,7 +2081,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.abort.set(true);
}
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(errors);
self.abort.set(true);

View File

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

View File

@@ -83,7 +83,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
});
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;
}
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,
// 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) =
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;
}
@@ -2102,7 +2102,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
{
terrs.push(terr);
}
if !ocx.select_where_possible().is_empty() {
if !ocx.try_evaluate_obligations().is_empty() {
return false;
}
}
@@ -3440,7 +3440,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation);
if ocx.select_all_or_error().is_empty() {
if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return Ok((
self.tcx
.fn_trait_kind_from_def_id(trait_def_id)

View File

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

View File

@@ -25,7 +25,7 @@ impl<'tcx> InferCtxt<'tcx> {
let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, a, b) else {
return false;
};
ocx.select_where_possible().is_empty()
ocx.try_evaluate_obligations().is_empty()
})
}
@@ -124,7 +124,7 @@ impl<'tcx> InferCtxt<'tcx> {
param_env,
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.
// 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.

View File

@@ -60,7 +60,7 @@ struct ObligationStorage<'tcx> {
/// Obligations which resulted in an overflow in fulfillment itself.
///
/// 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.
overflowed: Vec<PredicateObligation<'tcx>>,
pending: PendingObligations<'tcx>,
@@ -101,7 +101,7 @@ impl<'tcx> ObligationStorage<'tcx> {
// 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
// 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.
// FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
self.overflowed.extend(
@@ -179,7 +179,7 @@ where
.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());
let mut errors = Vec::new();
loop {

View File

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

View File

@@ -79,7 +79,7 @@ where
stalled_coroutine_goals: vec![],
};
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) }
}
@@ -128,7 +128,7 @@ where
);
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,
// so we can super fold here.
@@ -143,8 +143,8 @@ where
Ok(result)
}
fn select_all_and_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> {
let errors = self.fulfill_cx.select_where_possible(self.at.infcx);
fn evaluate_all_error_on_ambiguity_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> {
let errors = self.fulfill_cx.try_evaluate_obligations(self.at.infcx);
if !errors.is_empty() {
return Err(errors);
}

View File

@@ -155,7 +155,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
// an additional sanity check.
let ocx = ObligationCtxt::new(&infcx);
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() {
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);
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() {
assert!(
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 ocx = ObligationCtxt::new_with_diagnostics(infcx);
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.
// Ambiguities do not prove the disjointness of two impls.
let (errors, ambiguities): (Vec<_>, Vec<_>) =
@@ -623,7 +623,7 @@ fn try_prove_negated_where_clause<'tcx>(
param_env,
negative_predicate,
));
if !ocx.select_all_or_error().is_empty() {
if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
return false;
}
@@ -743,7 +743,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
ty = ocx
.structurally_normalize_ty(&ObligationCause::dummy(), param_env, ty)
.map_err(|_| ())?;
if !ocx.select_where_possible().is_empty() {
if !ocx.try_evaluate_obligations().is_empty() {
return Err(());
}
}

View File

@@ -176,7 +176,7 @@ fn satisfied_from_param_env<'tcx>(
if self.infcx.probe(|_| {
let ocx = ObligationCtxt::new(self.infcx);
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 {
None => Some(Ok(c)),
@@ -217,7 +217,7 @@ fn satisfied_from_param_env<'tcx>(
if let Some(Ok(c)) = single_match {
let ocx = ObligationCtxt::new(infcx);
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;
}

View File

@@ -202,14 +202,30 @@ where
.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]
pub fn select_where_possible(&self) -> Vec<E> {
self.engine.borrow_mut().select_where_possible(self.infcx)
pub fn try_evaluate_obligations(&self) -> Vec<E> {
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]
pub fn select_all_or_error(&self) -> Vec<E> {
self.engine.borrow_mut().select_all_or_error(self.infcx)
pub fn evaluate_obligations_error_on_ambiguity(&self) -> Vec<E> {
self.engine.borrow_mut().evaluate_obligations_error_on_ambiguity(self.infcx)
}
/// 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)
/// satisfied. The job is to track which are satisfied, which yielded
/// 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
/// ambiguous. This may be helpful in pushing type inference
/// 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.
pub struct FulfillmentContext<'tcx, E: 'tcx> {
/// A list of all obligations that have been registered with this
@@ -163,7 +163,7 @@ where
.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);
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),
));
if !ocx.select_all_or_error().is_empty() {
if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
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),
);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Fulfill(errors)));
continue;
@@ -235,7 +235,7 @@ pub fn all_fields_implement_trait<'tcx>(
ObligationCause::dummy_with_span(field_ty_span)
};
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,
// 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,
trait_def_id,
);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
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);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
match errors.as_slice() {
// Only known to hold if we did no inference.
[] => infcx.resolve_vars_if_possible(goal) == goal,
@@ -273,7 +273,7 @@ fn do_normalize_predicates<'tcx>(
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
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() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
@@ -738,13 +738,13 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
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
// some currently undetected overlap between `dyn Trait: Trait` built-in
// vs user-written impls to AMBIGUOUS, this may return ambiguity even
// with no infer vars. There may also be ways to encounter ambiguity due
// to post-mono overflow.
let true_errors = ocx.select_where_possible();
let true_errors = ocx.try_evaluate_obligations();
if !true_errors.is_empty() {
return true;
}
@@ -853,7 +853,7 @@ fn is_impossible_associated_item(
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligations(predicates_for_trait);
!ocx.select_where_possible().is_empty()
!ocx.try_evaluate_obligations().is_empty()
}
pub fn provide(providers: &mut Providers) {

View File

@@ -73,7 +73,7 @@ impl<'tcx> At<'_, 'tcx> {
let value = self
.normalize(value)
.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);
if errors.is_empty() {
Ok(value)

View File

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

View File

@@ -96,7 +96,7 @@ impl<'tcx> InferCtxt<'tcx> {
let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation.clone());
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() {
return Ok(EvaluationResult::EvaluatedToErr);
} else {

View File

@@ -94,7 +94,7 @@ where
let value = op(&ocx).map_err(|_| {
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() {
Ok(value)
} 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 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.tcx.def_span(source_impl),
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);
ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
// no dice!
debug!(
@@ -295,7 +295,7 @@ pub(super) fn specializes(
let ocx = ObligationCtxt::new(&infcx);
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.tcx.def_span(specializing_impl_def_id),
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);
ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
// no dice!
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() {
// no dice!
debug!(

View File

@@ -52,7 +52,7 @@ impl<'tcx> At<'_, 'tcx> {
);
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() {
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`
// contains unbound type parameters. It could be a slight
// optimization to stop iterating early.
let errors = ocx.select_all_or_error();
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if !errors.is_empty() {
// `rustc_monomorphize::collector` assumes there are no type errors.
// 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()),
)
}));
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_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).
// In that case, we may only realize a cycle error when calling
// `normalize_erasing_regions` in mono.
let errors = ocx.select_where_possible();
let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
// Rustdoc may attempt to normalize type alias types which are 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
// 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) {

View File

@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let cause = traits::ObligationCause::misc(span, fn_def_id);
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
// 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);
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)

View File

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

View File

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

View File

@@ -2151,7 +2151,7 @@ impl<'db> InferenceContext<'db> {
expected_output.to_nextsolver(interner),
formal_output,
)?;
if !ocx.select_where_possible().is_empty() {
if !ocx.try_evaluate_obligations().is_empty() {
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) {
self.fulfillment_cx.select_where_possible(&self.infer_ctxt);
self.fulfillment_cx.try_evaluate_obligations(&self.infer_ctxt);
}
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);
ctxt.register_obligations(infer_ok.into_obligations());
// 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));
@@ -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
} else {
IsValidCandidate::No

View File

@@ -54,7 +54,7 @@ struct ObligationStorage<'db> {
/// Obligations which resulted in an overflow in fulfillment itself.
///
/// 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.
overflowed: Vec<PredicateObligation<'db>>,
pending: PendingObligations<'db>,
@@ -95,7 +95,7 @@ impl<'db> ObligationStorage<'db> {
// 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
// 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.
// FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
self.overflowed.extend(
@@ -131,7 +131,7 @@ impl<'db> FulfillmentCtxt<'db> {
infcx: &InferCtxt<'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());
self.obligations.register(obligation, None);
}
@@ -141,7 +141,7 @@ impl<'db> FulfillmentCtxt<'db> {
infcx: &InferCtxt<'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());
obligations.into_iter().for_each(|obligation| self.obligations.register(obligation, None));
}
@@ -158,7 +158,7 @@ impl<'db> FulfillmentCtxt<'db> {
.collect()
}
pub(crate) fn select_where_possible(
pub(crate) fn try_evaluate_obligations(
&mut self,
infcx: &InferCtxt<'db>,
) -> Vec<NextSolverError<'db>> {
@@ -223,11 +223,11 @@ impl<'db> FulfillmentCtxt<'db> {
errors
}
pub(crate) fn select_all_or_error(
pub(crate) fn evaluate_obligations_error_on_ambiguity(
&mut self,
infcx: &InferCtxt<'db>,
) -> Vec<NextSolverError<'db>> {
let errors = self.select_where_possible(infcx);
let errors = self.try_evaluate_obligations(infcx);
if !errors.is_empty() {
return errors;
}

View File

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

View File

@@ -77,7 +77,7 @@ where
stalled_coroutine_goals: vec![],
};
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) }
}
@@ -138,7 +138,7 @@ impl<'db> NormalizationFolder<'_, 'db> {
fn select_all_and_stall_coroutine_predicates(
&mut self,
) -> 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() {
return Err(errors);
}

View File

@@ -144,13 +144,13 @@ impl<'a, 'db> ObligationCtxt<'a, 'db> {
}
#[must_use]
pub fn select_where_possible(&mut self) -> Vec<NextSolverError<'db>> {
self.engine.select_where_possible(self.infcx)
pub fn try_evaluate_obligations(&mut self) -> Vec<NextSolverError<'db>> {
self.engine.try_evaluate_obligations(self.infcx)
}
#[must_use]
pub fn select_all_or_error(&mut self) -> Vec<NextSolverError<'db>> {
self.engine.select_all_or_error(self.infcx)
pub fn evaluate_obligations_error_on_ambiguity(&mut self) -> Vec<NextSolverError<'db>> {
self.engine.evaluate_obligations_error_on_ambiguity(self.infcx)
}
/// 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);
let errors = fulfill_cx.select_where_possible(self.infcx);
let errors = fulfill_cx.try_evaluate_obligations(self.infcx);
if !errors.is_empty() {
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)`.
// For us to try and prove a `Subtype(impl Default, u32)` obligation,
// 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 assign_tup = &mut (foo(), 1u32);
tup = assign_tup;