mod engine;
pub mod error_reporting;
mod project;
mod structural_impls;
pub mod util;
use std::cmp;
use std::hash::{Hash, Hasher};
use hir::def_id::LocalDefId;
use rustc_hir as hir;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
use rustc_span::Span;
pub use self::ImplSource::*;
pub use self::SelectionError::*;
use crate::infer::InferCtxt;
pub use self::engine::{TraitEngine, TraitEngineExt};
pub use self::project::MismatchedProjectionTypes;
pub(crate) use self::project::UndoLog;
pub use self::project::{
Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
ProjectionCacheStorage, Reveal,
};
pub use rustc_middle::traits::*;
#[derive(Clone)]
pub struct Obligation<'tcx, T> {
pub cause: ObligationCause<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
pub predicate: T,
pub recursion_depth: usize,
}
impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
#[inline]
fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
self.param_env == other.param_env && self.predicate == other.predicate
}
}
impl<T: Eq> Eq for Obligation<'_, T> {}
impl<T: Hash> Hash for Obligation<'_, T> {
fn hash<H: Hasher>(&self, state: &mut H) -> () {
self.param_env.hash(state);
self.predicate.hash(state);
}
}
impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
fn from(value: Obligation<'tcx, P>) -> Self {
solve::Goal { param_env: value.param_env, predicate: value.predicate }
}
}
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
impl<'tcx> PredicateObligation<'tcx> {
pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> {
Some(PredicateObligation {
cause: self.cause.clone(),
param_env: self.param_env,
predicate: self.predicate.flip_polarity(tcx)?,
recursion_depth: self.recursion_depth,
})
}
}
impl<'tcx> PolyTraitObligation<'tcx> {
pub fn derived_cause(
&self,
variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
) -> ObligationCause<'tcx> {
self.cause.clone().derived_cause(self.predicate, variant)
}
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PredicateObligation<'_>, 48);
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
pub type ObligationInspector<'tcx> =
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
pub struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>,
pub code: FulfillmentErrorCode<'tcx>,
pub root_obligation: PredicateObligation<'tcx>,
}
#[derive(Clone)]
pub enum FulfillmentErrorCode<'tcx> {
Cycle(Vec<PredicateObligation<'tcx>>),
SelectionError(SelectionError<'tcx>),
ProjectionError(MismatchedProjectionTypes<'tcx>),
SubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), ConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
Ambiguity {
overflow: Option<bool>,
},
}
impl<'tcx, O> Obligation<'tcx, O> {
pub fn new(
tcx: TyCtxt<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
predicate: impl ToPredicate<'tcx, O>,
) -> Obligation<'tcx, O> {
Self::with_depth(tcx, cause, 0, param_env, predicate)
}
pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
}
pub fn with_depth(
tcx: TyCtxt<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
predicate: impl ToPredicate<'tcx, O>,
) -> Obligation<'tcx, O> {
let predicate = predicate.to_predicate(tcx);
Obligation { cause, param_env, recursion_depth, predicate }
}
pub fn misc(
tcx: TyCtxt<'tcx>,
span: Span,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
trait_ref: impl ToPredicate<'tcx, O>,
) -> Obligation<'tcx, O> {
Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
}
pub fn with<P>(
&self,
tcx: TyCtxt<'tcx>,
value: impl ToPredicate<'tcx, P>,
) -> Obligation<'tcx, P> {
Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
}
}
impl<'tcx> FulfillmentError<'tcx> {
pub fn new(
obligation: PredicateObligation<'tcx>,
code: FulfillmentErrorCode<'tcx>,
root_obligation: PredicateObligation<'tcx>,
) -> FulfillmentError<'tcx> {
FulfillmentError { obligation, code, root_obligation }
}
}
impl<'tcx> PolyTraitObligation<'tcx> {
pub fn polarity(&self) -> ty::ImplPolarity {
self.predicate.skip_binder().polarity
}
pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
self.predicate.map_bound(|p| p.self_ty())
}
}