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 5 mod engine; 6 pub mod error_reporting; 7 mod project; 8 mod structural_impls; 9 pub mod util; 10 11 use std::cmp; 12 13 use hir::def_id::LocalDefId; 14 use rustc_hir as hir; 15 use rustc_middle::ty::error::{ExpectedFound, TypeError}; 16 use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; 17 use rustc_span::Span; 18 19 pub use self::FulfillmentErrorCode::*; 20 pub use self::ImplSource::*; 21 pub use self::ObligationCauseCode::*; 22 pub use self::SelectionError::*; 23 24 pub use self::engine::{TraitEngine, TraitEngineExt}; 25 pub use self::project::MismatchedProjectionTypes; 26 pub(crate) use self::project::UndoLog; 27 pub use self::project::{ 28 Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, 29 ProjectionCacheStorage, Reveal, 30 }; 31 pub use rustc_middle::traits::*; 32 33 /// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for 34 /// which the "impl_source" must be found. The process of finding an "impl_source" is 35 /// called "resolving" the `Obligation`. This process consists of 36 /// either identifying an `impl` (e.g., `impl Eq for i32`) that 37 /// satisfies the obligation, or else finding a bound that is in 38 /// scope. The eventual result is usually a `Selection` (defined below). 39 #[derive(Clone, PartialEq, Eq, Hash)] 40 pub struct Obligation<'tcx, T> { 41 /// The reason we have to prove this thing. 42 pub cause: ObligationCause<'tcx>, 43 44 /// The environment in which we should prove this thing. 45 pub param_env: ty::ParamEnv<'tcx>, 46 47 /// The thing we are trying to prove. 48 pub predicate: T, 49 50 /// If we started proving this as a result of trying to prove 51 /// something else, track the total depth to ensure termination. 52 /// If this goes over a certain threshold, we abort compilation -- 53 /// in such cases, we can not say whether or not the predicate 54 /// holds for certain. Stupid halting problem; such a drag. 55 pub recursion_depth: usize, 56 } 57 58 impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> { from(value: Obligation<'tcx, P>) -> Self59 fn from(value: Obligation<'tcx, P>) -> Self { 60 solve::Goal { param_env: value.param_env, predicate: value.predicate } 61 } 62 } 63 64 pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; 65 pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; 66 pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; 67 68 impl<'tcx> PredicateObligation<'tcx> { 69 /// Flips the polarity of the inner predicate. 70 /// 71 /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>>72 pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> { 73 Some(PredicateObligation { 74 cause: self.cause.clone(), 75 param_env: self.param_env, 76 predicate: self.predicate.flip_polarity(tcx)?, 77 recursion_depth: self.recursion_depth, 78 }) 79 } 80 without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx>81 pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> { 82 self.param_env = self.param_env.without_const(); 83 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() { 84 self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const())))); 85 } 86 self 87 } 88 } 89 90 impl<'tcx> PolyTraitObligation<'tcx> { 91 /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. is_const(&self) -> bool92 pub fn is_const(&self) -> bool { 93 matches!( 94 (self.predicate.skip_binder().constness, self.param_env.constness()), 95 (ty::BoundConstness::ConstIfConst, hir::Constness::Const) 96 ) 97 } 98 derived_cause( &self, variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx>99 pub fn derived_cause( 100 &self, 101 variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, 102 ) -> ObligationCause<'tcx> { 103 self.cause.clone().derived_cause(self.predicate, variant) 104 } 105 } 106 107 // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. 108 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] 109 static_assert_size!(PredicateObligation<'_>, 48); 110 111 pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>; 112 113 pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; 114 115 pub struct FulfillmentError<'tcx> { 116 pub obligation: PredicateObligation<'tcx>, 117 pub code: FulfillmentErrorCode<'tcx>, 118 /// Diagnostics only: the 'root' obligation which resulted in 119 /// the failure to process `obligation`. This is the obligation 120 /// that was initially passed to `register_predicate_obligation` 121 pub root_obligation: PredicateObligation<'tcx>, 122 } 123 124 #[derive(Clone)] 125 pub enum FulfillmentErrorCode<'tcx> { 126 /// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented. 127 CodeCycle(Vec<PredicateObligation<'tcx>>), 128 CodeSelectionError(SelectionError<'tcx>), 129 CodeProjectionError(MismatchedProjectionTypes<'tcx>), 130 CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate 131 CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>), 132 CodeAmbiguity { 133 /// Overflow reported from the new solver `-Ztrait-solver=next`, which will 134 /// be reported as an regular error as opposed to a fatal error. 135 overflow: bool, 136 }, 137 } 138 139 impl<'tcx, O> Obligation<'tcx, O> { new( tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, predicate: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O>140 pub fn new( 141 tcx: TyCtxt<'tcx>, 142 cause: ObligationCause<'tcx>, 143 param_env: ty::ParamEnv<'tcx>, 144 predicate: impl ToPredicate<'tcx, O>, 145 ) -> Obligation<'tcx, O> { 146 Self::with_depth(tcx, cause, 0, param_env, predicate) 147 } 148 149 /// We often create nested obligations without setting the correct depth. 150 /// 151 /// To deal with this evaluate and fulfill explicitly update the depth 152 /// of nested obligations using this function. set_depth_from_parent(&mut self, parent_depth: usize)153 pub fn set_depth_from_parent(&mut self, parent_depth: usize) { 154 self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth); 155 } 156 with_depth( tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, predicate: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O>157 pub fn with_depth( 158 tcx: TyCtxt<'tcx>, 159 cause: ObligationCause<'tcx>, 160 recursion_depth: usize, 161 param_env: ty::ParamEnv<'tcx>, 162 predicate: impl ToPredicate<'tcx, O>, 163 ) -> Obligation<'tcx, O> { 164 let predicate = predicate.to_predicate(tcx); 165 Obligation { cause, param_env, recursion_depth, predicate } 166 } 167 misc( tcx: TyCtxt<'tcx>, span: Span, body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, trait_ref: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O>168 pub fn misc( 169 tcx: TyCtxt<'tcx>, 170 span: Span, 171 body_id: LocalDefId, 172 param_env: ty::ParamEnv<'tcx>, 173 trait_ref: impl ToPredicate<'tcx, O>, 174 ) -> Obligation<'tcx, O> { 175 Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref) 176 } 177 with<P>( &self, tcx: TyCtxt<'tcx>, value: impl ToPredicate<'tcx, P>, ) -> Obligation<'tcx, P>178 pub fn with<P>( 179 &self, 180 tcx: TyCtxt<'tcx>, 181 value: impl ToPredicate<'tcx, P>, 182 ) -> Obligation<'tcx, P> { 183 Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value) 184 } 185 } 186 187 impl<'tcx> FulfillmentError<'tcx> { new( obligation: PredicateObligation<'tcx>, code: FulfillmentErrorCode<'tcx>, root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx>188 pub fn new( 189 obligation: PredicateObligation<'tcx>, 190 code: FulfillmentErrorCode<'tcx>, 191 root_obligation: PredicateObligation<'tcx>, 192 ) -> FulfillmentError<'tcx> { 193 FulfillmentError { obligation, code, root_obligation } 194 } 195 } 196 197 impl<'tcx> PolyTraitObligation<'tcx> { polarity(&self) -> ty::ImplPolarity198 pub fn polarity(&self) -> ty::ImplPolarity { 199 self.predicate.skip_binder().polarity 200 } 201 self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>>202 pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { 203 self.predicate.map_bound(|p| p.self_ty()) 204 } 205 } 206