rustc_infer/traits/
mod.rs

1//! Trait Resolution. See the [rustc-dev-guide] for more information on how this works.
2//!
3//! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
4
5mod 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/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
33/// which the "impl_source" must be found. The process of finding an "impl_source" is
34/// called "resolving" the `Obligation`. This process consists of
35/// either identifying an `impl` (e.g., `impl Eq for i32`) that
36/// satisfies the obligation, or else finding a bound that is in
37/// scope. The eventual result is usually a `Selection` (defined below).
38#[derive(Clone)]
39pub struct Obligation<'tcx, T> {
40    /// The reason we have to prove this thing.
41    pub cause: ObligationCause<'tcx>,
42
43    /// The environment in which we should prove this thing.
44    pub param_env: ty::ParamEnv<'tcx>,
45
46    /// The thing we are trying to prove.
47    pub predicate: T,
48
49    /// If we started proving this as a result of trying to prove
50    /// something else, track the total depth to ensure termination.
51    /// If this goes over a certain threshold, we abort compilation --
52    /// in such cases, we can not say whether or not the predicate
53    /// holds for certain. Stupid halting problem; such a drag.
54    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        // Ignore `cause` and `recursion_depth`. This is a small performance
61        // win for a few crates, and a huge performance win for the crate in
62        // https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
63        // stresses the trait system.
64        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        // See the comment on `Obligation::eq`.
73        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    /// Flips the polarity of the inner predicate.
92    ///
93    /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
94    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// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
114#[cfg(target_pointer_width = "64")]
115rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48);
116
117pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
118
119/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation
120/// of root obligations.
121pub 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    /// We often create nested obligations without setting the correct depth.
135    ///
136    /// To deal with this evaluate and fulfill explicitly update the depth
137    /// of nested obligations using this function.
138    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}