Separate trait selection from ambiguity reporting.

This commit is contained in:
Camille GILLOT 2022-09-28 18:16:23 +02:00
parent 2870ce01b8
commit cb873b2d93
8 changed files with 25 additions and 30 deletions

View File

@ -525,8 +525,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
pub(in super::super) fn select_all_obligations_or_error(&self) { pub(in super::super) fn report_ambiguity_errors(&self) {
let mut errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self); let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors();
if !errors.is_empty() { if !errors.is_empty() {
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors); self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);

View File

@ -301,7 +301,11 @@ fn typeck_with_fallback<'tcx>(
fcx.require_type_is_sized(ty, span, code); fcx.require_type_is_sized(ty, span, code);
} }
fcx.select_all_obligations_or_error(); fcx.select_obligations_where_possible(|_| {});
if let None = fcx.infcx.tainted_by_errors() {
fcx.report_ambiguity_errors();
}
if let None = fcx.infcx.tainted_by_errors() { if let None = fcx.infcx.tainted_by_errors() {
fcx.check_transmutes(); fcx.check_transmutes();

View File

@ -17,7 +17,7 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
use crate::traits::query::{Fallible, NoSolution}; use crate::traits::query::{Fallible, NoSolution};
use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{PredicateObligations, TraitEngine}; use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;

View File

@ -36,10 +36,10 @@ pub trait TraitEngine<'tcx>: 'tcx {
obligation: PredicateObligation<'tcx>, obligation: PredicateObligation<'tcx>,
); );
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>; fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>;
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>; fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
} }
@ -49,6 +49,8 @@ pub trait TraitEngineExt<'tcx> {
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
); );
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
} }
impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
@ -61,4 +63,13 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
self.register_predicate_obligation(infcx, obligation); self.register_predicate_obligation(infcx, obligation);
} }
} }
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
let errors = self.select_where_possible(infcx);
if !errors.is_empty() {
return errors;
}
self.collect_remaining_errors()
}
} }

View File

@ -40,12 +40,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
self.obligations.push(obligation); self.obligations.push(obligation);
} }
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
let errors = self.select_where_possible(infcx);
if !errors.is_empty() {
return errors;
}
self.obligations self.obligations
.drain(..) .drain(..)
.map(|obligation| FulfillmentError { .map(|obligation| FulfillmentError {

View File

@ -40,15 +40,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.obligations.insert(obligation); self.obligations.insert(obligation);
} }
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
{
let errors = self.select_where_possible(infcx);
if !errors.is_empty() {
return errors;
}
}
// any remaining obligations are errors // any remaining obligations are errors
self.obligations self.obligations
.iter() .iter()

View File

@ -132,14 +132,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] }); .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
} }
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
{
let errors = self.select_where_possible(infcx);
if !errors.is_empty() {
return errors;
}
}
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
} }

View File

@ -4,7 +4,7 @@
// general routines. // general routines.
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_infer::traits::FulfillmentErrorCode; use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
use rustc_middle::traits::CodegenObligationError; use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;