use std::fmt::Debug; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Ty, Upcast}; use super::{ObligationCause, PredicateObligation, PredicateObligations}; use crate::infer::InferCtxt; use crate::traits::Obligation; /// A trait error with most of its information removed. This is the error /// returned by an `ObligationCtxt` by default, and suitable if you just /// want to see if a predicate holds, and don't particularly care about the /// error itself (except for if it's an ambiguity or true error). /// /// use `ObligationCtxt::new_with_diagnostics` to get a `FulfillmentError`. #[derive(Clone, Debug)] pub enum ScrubbedTraitError<'tcx> { /// A real error. This goal definitely does not hold. TrueError, /// An ambiguity. This goal may hold if further inference is done. Ambiguity, /// An old-solver-style cycle error, which will fatal. This is not /// returned by the new solver. Cycle(PredicateObligations<'tcx>), } impl<'tcx> ScrubbedTraitError<'tcx> { pub fn is_true_error(&self) -> bool { match self { ScrubbedTraitError::TrueError => true, ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false, } } } pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { /// Requires that `ty` must implement the trait with `def_id` in /// the given environment. This trait must not have any type /// parameters (except for `Self`). fn register_bound( &mut self, infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, def_id: DefId, cause: ObligationCause<'tcx>, ) { let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]); self.register_predicate_obligation( infcx, Obligation { cause, recursion_depth: 0, param_env, predicate: trait_ref.upcast(infcx.tcx), }, ); } fn register_predicate_obligation( &mut self, infcx: &InferCtxt<'tcx>, obligation: PredicateObligation<'tcx>, ); fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'tcx>, obligations: PredicateObligations<'tcx>, ) { for obligation in obligations { self.register_predicate_obligation(infcx, obligation); } } #[must_use] fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec; fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec; #[must_use] 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(infcx) } fn has_pending_obligations(&self) -> bool; 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 /// successful and returned. fn drain_stalled_obligations_for_coroutines( &mut self, infcx: &InferCtxt<'tcx>, ) -> PredicateObligations<'tcx>; } pub trait FromSolverError<'tcx, E>: Debug + 'tcx { fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self; }