diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index e9858aef6d0b..42f4b49889a2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -525,8 +525,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - pub(in super::super) fn select_all_obligations_or_error(&self) { - let mut errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self); + pub(in super::super) fn report_ambiguity_errors(&self) { + let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors(); if !errors.is_empty() { self.adjust_fulfillment_errors_for_expr_obligation(&mut errors); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 04ac9c085ea2..899ec9ff9de0 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -301,7 +301,11 @@ fn typeck_with_fallback<'tcx>( 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() { fcx.check_transmutes(); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 3d49182f0b81..9174bd524bee 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -17,7 +17,7 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; 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_index::vec::Idx; use rustc_index::vec::IndexVec; diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index fcde00056cbf..805eb95e3161 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -36,10 +36,10 @@ pub trait TraitEngine<'tcx>: 'tcx { obligation: PredicateObligation<'tcx>, ); - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; - fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; + fn collect_remaining_errors(&mut self) -> Vec>; + fn pending_obligations(&self) -> Vec>; } @@ -49,6 +49,8 @@ pub trait TraitEngineExt<'tcx> { infcx: &InferCtxt<'tcx>, obligations: impl IntoIterator>, ); + + fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; } 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); } } + + fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { + let errors = self.select_where_possible(infcx); + if !errors.is_empty() { + return errors; + } + + self.collect_remaining_errors() + } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 278024b22760..45507ed4dcc9 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -40,12 +40,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { self.obligations.push(obligation); } - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - let errors = self.select_where_possible(infcx); - if !errors.is_empty() { - return errors; - } - + fn collect_remaining_errors(&mut self) -> Vec> { self.obligations .drain(..) .map(|obligation| FulfillmentError { diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 61d09189798e..76e31845797a 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -40,15 +40,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.obligations.insert(obligation); } - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - { - let errors = self.select_where_possible(infcx); - - if !errors.is_empty() { - return errors; - } - } - + fn collect_remaining_errors(&mut self) -> Vec> { // any remaining obligations are errors self.obligations .iter() diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 5a58d37e1836..111a2d034daa 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -132,14 +132,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] }); } - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - { - let errors = self.select_where_possible(infcx); - if !errors.is_empty() { - return errors; - } - } - + fn collect_remaining_errors(&mut self) -> Vec> { self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() } diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index c0da8a8169e5..6f81d343e0fd 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -4,7 +4,7 @@ // general routines. 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::ty::{self, TyCtxt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;