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_middle::traits::query::NoSolution;
16use rustc_middle::traits::solve::Certainty;
17pub use rustc_middle::traits::*;
18use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
19use rustc_span::Span;
20use thin_vec::ThinVec;
21
22pub use self::ImplSource::*;
23pub use self::SelectionError::*;
24pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
25pub(crate) use self::project::UndoLog;
26pub use self::project::{
27 MismatchedProjectionTypes, Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry,
28 ProjectionCacheKey, ProjectionCacheStorage,
29};
30use crate::infer::InferCtxt;
31
32#[derive(Clone)]
39pub struct Obligation<'tcx, T> {
40 pub cause: ObligationCause<'tcx>,
42
43 pub param_env: ty::ParamEnv<'tcx>,
45
46 pub predicate: T,
48
49 pub recursion_depth: usize,
55}
56
57impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
58 #[inline]
59 fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
60 self.param_env == other.param_env && self.predicate == other.predicate
65 }
66}
67
68impl<T: Eq> Eq for Obligation<'_, T> {}
69
70impl<T: Hash> Hash for Obligation<'_, T> {
71 fn hash<H: Hasher>(&self, state: &mut H) -> () {
72 self.param_env.hash(state);
74 self.predicate.hash(state);
75 }
76}
77
78impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
79 fn from(value: Obligation<'tcx, P>) -> Self {
80 solve::Goal { param_env: value.param_env, predicate: value.predicate }
81 }
82}
83
84pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
85pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
86pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
87
88pub type PredicateObligations<'tcx> = ThinVec<PredicateObligation<'tcx>>;
89
90impl<'tcx> PredicateObligation<'tcx> {
91 pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> {
95 Some(PredicateObligation {
96 cause: self.cause.clone(),
97 param_env: self.param_env,
98 predicate: self.predicate.flip_polarity(tcx)?,
99 recursion_depth: self.recursion_depth,
100 })
101 }
102}
103
104impl<'tcx> PolyTraitObligation<'tcx> {
105 pub fn derived_cause(
106 &self,
107 variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
108 ) -> ObligationCause<'tcx> {
109 self.cause.clone().derived_cause(self.predicate, variant)
110 }
111}
112
113#[cfg(target_pointer_width = "64")]
115rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48);
116
117pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
118
119pub type ObligationInspector<'tcx> =
122 fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
123
124impl<'tcx, O> Obligation<'tcx, O> {
125 pub fn new(
126 tcx: TyCtxt<'tcx>,
127 cause: ObligationCause<'tcx>,
128 param_env: ty::ParamEnv<'tcx>,
129 predicate: impl Upcast<TyCtxt<'tcx>, O>,
130 ) -> Obligation<'tcx, O> {
131 Self::with_depth(tcx, cause, 0, param_env, predicate)
132 }
133
134 pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
139 self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
140 }
141
142 pub fn with_depth(
143 tcx: TyCtxt<'tcx>,
144 cause: ObligationCause<'tcx>,
145 recursion_depth: usize,
146 param_env: ty::ParamEnv<'tcx>,
147 predicate: impl Upcast<TyCtxt<'tcx>, O>,
148 ) -> Obligation<'tcx, O> {
149 let predicate = predicate.upcast(tcx);
150 Obligation { cause, param_env, recursion_depth, predicate }
151 }
152
153 pub fn misc(
154 tcx: TyCtxt<'tcx>,
155 span: Span,
156 body_id: LocalDefId,
157 param_env: ty::ParamEnv<'tcx>,
158 trait_ref: impl Upcast<TyCtxt<'tcx>, O>,
159 ) -> Obligation<'tcx, O> {
160 Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
161 }
162
163 pub fn with<P>(
164 &self,
165 tcx: TyCtxt<'tcx>,
166 value: impl Upcast<TyCtxt<'tcx>, P>,
167 ) -> Obligation<'tcx, P> {
168 Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
169 }
170}
171
172impl<'tcx> PolyTraitObligation<'tcx> {
173 pub fn polarity(&self) -> ty::PredicatePolarity {
174 self.predicate.skip_binder().polarity
175 }
176
177 pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
178 self.predicate.map_bound(|p| p.self_ty())
179 }
180}