]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | //! Trait Resolution. See the [rustc-dev-guide] for more information on how this works. |
74b04a01 | 2 | //! |
ba9703b0 | 3 | //! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html |
74b04a01 | 4 | |
74b04a01 XL |
5 | mod engine; |
6 | pub mod error_reporting; | |
74b04a01 | 7 | mod project; |
74b04a01 | 8 | mod structural_impls; |
ba9703b0 | 9 | pub mod util; |
74b04a01 | 10 | |
74b04a01 | 11 | use rustc_hir as hir; |
ba9703b0 | 12 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
3c0e092e | 13 | use rustc_middle::ty::{self, Const, Ty, TyCtxt}; |
ba9703b0 | 14 | use rustc_span::Span; |
74b04a01 XL |
15 | |
16 | pub use self::FulfillmentErrorCode::*; | |
f035d41b | 17 | pub use self::ImplSource::*; |
74b04a01 XL |
18 | pub use self::ObligationCauseCode::*; |
19 | pub use self::SelectionError::*; | |
74b04a01 | 20 | |
74b04a01 | 21 | pub use self::engine::{TraitEngine, TraitEngineExt}; |
74b04a01 | 22 | pub use self::project::MismatchedProjectionTypes; |
f9f354fc | 23 | pub(crate) use self::project::UndoLog; |
74b04a01 | 24 | pub use self::project::{ |
ba9703b0 | 25 | Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, |
f9f354fc | 26 | ProjectionCacheStorage, Reveal, |
74b04a01 | 27 | }; |
ba9703b0 | 28 | pub use rustc_middle::traits::*; |
74b04a01 | 29 | |
f035d41b | 30 | /// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for |
94222f64 | 31 | /// which the "impl_source" must be found. The process of finding an "impl_source" is |
74b04a01 | 32 | /// called "resolving" the `Obligation`. This process consists of |
f035d41b XL |
33 | /// either identifying an `impl` (e.g., `impl Eq for i32`) that |
34 | /// satisfies the obligation, or else finding a bound that is in | |
74b04a01 XL |
35 | /// scope. The eventual result is usually a `Selection` (defined below). |
36 | #[derive(Clone, PartialEq, Eq, Hash)] | |
37 | pub struct Obligation<'tcx, T> { | |
38 | /// The reason we have to prove this thing. | |
39 | pub cause: ObligationCause<'tcx>, | |
40 | ||
41 | /// The environment in which we should prove this thing. | |
42 | pub param_env: ty::ParamEnv<'tcx>, | |
43 | ||
44 | /// The thing we are trying to prove. | |
45 | pub predicate: T, | |
46 | ||
47 | /// If we started proving this as a result of trying to prove | |
48 | /// something else, track the total depth to ensure termination. | |
49 | /// If this goes over a certain threshold, we abort compilation -- | |
50 | /// in such cases, we can not say whether or not the predicate | |
51 | /// holds for certain. Stupid halting problem; such a drag. | |
52 | pub recursion_depth: usize, | |
53 | } | |
54 | ||
55 | pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; | |
56 | pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; | |
57 | ||
a2a8927a | 58 | impl<'tcx> PredicateObligation<'tcx> { |
3c0e092e XL |
59 | /// Flips the polarity of the inner predicate. |
60 | /// | |
61 | /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. | |
62 | pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> { | |
63 | Some(PredicateObligation { | |
64 | cause: self.cause.clone(), | |
65 | param_env: self.param_env, | |
66 | predicate: self.predicate.flip_polarity(tcx)?, | |
67 | recursion_depth: self.recursion_depth, | |
68 | }) | |
69 | } | |
70 | } | |
71 | ||
a2a8927a XL |
72 | impl TraitObligation<'_> { |
73 | /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. | |
74 | pub fn is_const(&self) -> bool { | |
75 | match (self.predicate.skip_binder().constness, self.param_env.constness()) { | |
76 | (ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true, | |
77 | _ => false, | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
74b04a01 | 82 | // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. |
6a06907d | 83 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] |
a2a8927a | 84 | static_assert_size!(PredicateObligation<'_>, 48); |
74b04a01 | 85 | |
74b04a01 | 86 | pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>; |
74b04a01 | 87 | |
f035d41b | 88 | pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; |
74b04a01 XL |
89 | |
90 | pub struct FulfillmentError<'tcx> { | |
91 | pub obligation: PredicateObligation<'tcx>, | |
92 | pub code: FulfillmentErrorCode<'tcx>, | |
136023e0 XL |
93 | /// Diagnostics only: the 'root' obligation which resulted in |
94 | /// the failure to process `obligation`. This is the obligation | |
95 | /// that was initially passed to `register_predicate_obligation` | |
96 | pub root_obligation: PredicateObligation<'tcx>, | |
74b04a01 XL |
97 | } |
98 | ||
99 | #[derive(Clone)] | |
100 | pub enum FulfillmentErrorCode<'tcx> { | |
101 | CodeSelectionError(SelectionError<'tcx>), | |
102 | CodeProjectionError(MismatchedProjectionTypes<'tcx>), | |
103 | CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate | |
5099ac24 | 104 | CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>), |
74b04a01 XL |
105 | CodeAmbiguity, |
106 | } | |
107 | ||
74b04a01 XL |
108 | impl<'tcx, O> Obligation<'tcx, O> { |
109 | pub fn new( | |
110 | cause: ObligationCause<'tcx>, | |
111 | param_env: ty::ParamEnv<'tcx>, | |
112 | predicate: O, | |
113 | ) -> Obligation<'tcx, O> { | |
114 | Obligation { cause, param_env, recursion_depth: 0, predicate } | |
115 | } | |
116 | ||
ba9703b0 | 117 | pub fn with_depth( |
74b04a01 XL |
118 | cause: ObligationCause<'tcx>, |
119 | recursion_depth: usize, | |
120 | param_env: ty::ParamEnv<'tcx>, | |
121 | predicate: O, | |
122 | ) -> Obligation<'tcx, O> { | |
123 | Obligation { cause, param_env, recursion_depth, predicate } | |
124 | } | |
125 | ||
126 | pub fn misc( | |
127 | span: Span, | |
128 | body_id: hir::HirId, | |
129 | param_env: ty::ParamEnv<'tcx>, | |
130 | trait_ref: O, | |
131 | ) -> Obligation<'tcx, O> { | |
132 | Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref) | |
133 | } | |
134 | ||
135 | pub fn with<P>(&self, value: P) -> Obligation<'tcx, P> { | |
136 | Obligation { | |
137 | cause: self.cause.clone(), | |
138 | param_env: self.param_env, | |
139 | recursion_depth: self.recursion_depth, | |
140 | predicate: value, | |
141 | } | |
142 | } | |
143 | } | |
144 | ||
145 | impl<'tcx> FulfillmentError<'tcx> { | |
ba9703b0 | 146 | pub fn new( |
74b04a01 XL |
147 | obligation: PredicateObligation<'tcx>, |
148 | code: FulfillmentErrorCode<'tcx>, | |
136023e0 | 149 | root_obligation: PredicateObligation<'tcx>, |
74b04a01 | 150 | ) -> FulfillmentError<'tcx> { |
c295e0f8 | 151 | FulfillmentError { obligation, code, root_obligation } |
74b04a01 XL |
152 | } |
153 | } | |
154 | ||
155 | impl<'tcx> TraitObligation<'tcx> { | |
3c0e092e XL |
156 | pub fn polarity(&self) -> ty::ImplPolarity { |
157 | self.predicate.skip_binder().polarity | |
158 | } | |
159 | ||
cdc7bbd5 | 160 | pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { |
74b04a01 XL |
161 | self.predicate.map_bound(|p| p.self_ty()) |
162 | } | |
163 | } |