1mod engine;
6mod project;
7mod structural_impls;
8pub mod util;
9
10use std::cmp;
11use std::hash::{Hash, Hasher};
12
13use hir::def_id::LocalDefId;
14use rustc_hir as hir;
15use rustc_macros::{TypeFoldable, TypeVisitable};
16use rustc_middle::traits::query::NoSolution;
17use rustc_middle::traits::solve::Certainty;
18pub use rustc_middle::traits::*;
19use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
20use rustc_span::Span;
21use thin_vec::ThinVec;
22
23pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
24pub(crate) use self::project::UndoLog;
25pub use self::project::{
26    MismatchedProjectionTypes, Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry,
27    ProjectionCacheKey, ProjectionCacheStorage,
28};
29use crate::infer::InferCtxt;
30
31#[derive(Clone, TypeFoldable, TypeVisitable)]
38pub struct Obligation<'tcx, T> {
39    #[type_foldable(identity)]
41    #[type_visitable(ignore)]
42    pub cause: ObligationCause<'tcx>,
43
44    pub param_env: ty::ParamEnv<'tcx>,
46
47    pub predicate: T,
49
50    #[type_foldable(identity)]
56    #[type_visitable(ignore)]
57    pub recursion_depth: usize,
58}
59
60impl<'tcx, T: Copy> Obligation<'tcx, T> {
61    pub fn as_goal(&self) -> solve::Goal<'tcx, T> {
62        solve::Goal { param_env: self.param_env, predicate: self.predicate }
63    }
64}
65
66impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
67    #[inline]
68    fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
69        self.param_env == other.param_env && self.predicate == other.predicate
74    }
75}
76
77impl<T: Eq> Eq for Obligation<'_, T> {}
78
79impl<T: Hash> Hash for Obligation<'_, T> {
80    fn hash<H: Hasher>(&self, state: &mut H) -> () {
81        self.param_env.hash(state);
83        self.predicate.hash(state);
84    }
85}
86
87pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
88pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
89pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
90
91pub type PredicateObligations<'tcx> = ThinVec<PredicateObligation<'tcx>>;
92
93impl<'tcx> PredicateObligation<'tcx> {
94    pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> {
98        Some(PredicateObligation {
99            cause: self.cause.clone(),
100            param_env: self.param_env,
101            predicate: self.predicate.flip_polarity(tcx)?,
102            recursion_depth: self.recursion_depth,
103        })
104    }
105}
106
107impl<'tcx> PolyTraitObligation<'tcx> {
108    pub fn derived_cause(
109        &self,
110        variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
111    ) -> ObligationCause<'tcx> {
112        self.cause.clone().derived_cause(self.predicate, variant)
113    }
114}
115
116#[cfg(target_pointer_width = "64")]
118rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48);
119
120pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
121
122pub type ObligationInspector<'tcx> =
125    fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
126
127impl<'tcx, O> Obligation<'tcx, O> {
128    pub fn new(
129        tcx: TyCtxt<'tcx>,
130        cause: ObligationCause<'tcx>,
131        param_env: ty::ParamEnv<'tcx>,
132        predicate: impl Upcast<TyCtxt<'tcx>, O>,
133    ) -> Obligation<'tcx, O> {
134        Self::with_depth(tcx, cause, 0, param_env, predicate)
135    }
136
137    pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
142        self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
143    }
144
145    pub fn with_depth(
146        tcx: TyCtxt<'tcx>,
147        cause: ObligationCause<'tcx>,
148        recursion_depth: usize,
149        param_env: ty::ParamEnv<'tcx>,
150        predicate: impl Upcast<TyCtxt<'tcx>, O>,
151    ) -> Obligation<'tcx, O> {
152        let predicate = predicate.upcast(tcx);
153        Obligation { cause, param_env, recursion_depth, predicate }
154    }
155
156    pub fn misc(
157        tcx: TyCtxt<'tcx>,
158        span: Span,
159        body_id: LocalDefId,
160        param_env: ty::ParamEnv<'tcx>,
161        trait_ref: impl Upcast<TyCtxt<'tcx>, O>,
162    ) -> Obligation<'tcx, O> {
163        Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
164    }
165
166    pub fn with<P>(
167        &self,
168        tcx: TyCtxt<'tcx>,
169        value: impl Upcast<TyCtxt<'tcx>, P>,
170    ) -> Obligation<'tcx, P> {
171        Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
172    }
173}
174
175impl<'tcx> PolyTraitObligation<'tcx> {
176    pub fn polarity(&self) -> ty::PredicatePolarity {
177        self.predicate.skip_binder().polarity
178    }
179
180    pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
181        self.predicate.map_bound(|p| p.self_ty())
182    }
183}