]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
0531ce1d XL |
11 | //! Trait Resolution. See [rustc guide] for more info on how this works. |
12 | //! | |
8faf50e0 | 13 | //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html |
1a4d82fc JJ |
14 | |
15 | pub use self::SelectionError::*; | |
16 | pub use self::FulfillmentErrorCode::*; | |
17 | pub use self::Vtable::*; | |
18 | pub use self::ObligationCauseCode::*; | |
19 | ||
94b46f34 | 20 | use chalk_engine; |
476ff2be | 21 | use hir; |
54a0048b | 22 | use hir::def_id::DefId; |
ff7c6d11 | 23 | use infer::outlives::env::OutlivesEnvironment; |
ea8adc8c | 24 | use middle::region; |
8faf50e0 | 25 | use mir::interpret::ConstEvalErr; |
9e0c209e | 26 | use ty::subst::Substs; |
94b46f34 | 27 | use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, ToPredicate}; |
cc61c64b | 28 | use ty::error::{ExpectedFound, TypeError}; |
94b46f34 | 29 | use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor}; |
cc61c64b | 30 | use infer::{InferCtxt}; |
e9174d1e | 31 | |
0531ce1d | 32 | use rustc_data_structures::sync::Lrc; |
94b46f34 | 33 | use std::fmt::Debug; |
1a4d82fc JJ |
34 | use std::rc::Rc; |
35 | use syntax::ast; | |
3157f602 | 36 | use syntax_pos::{Span, DUMMY_SP}; |
1a4d82fc | 37 | |
ea8adc8c | 38 | pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult}; |
0531ce1d | 39 | pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; |
3157f602 | 40 | pub use self::project::MismatchedProjectionTypes; |
0531ce1d XL |
41 | pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type}; |
42 | pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal, Normalized}; | |
1a4d82fc JJ |
43 | pub use self::object_safety::ObjectSafetyViolation; |
44 | pub use self::object_safety::MethodViolationCode; | |
ea8adc8c | 45 | pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; |
54a0048b | 46 | pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; |
83c7162d | 47 | pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; |
ea8adc8c | 48 | pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; |
cc61c64b | 49 | pub use self::specialize::{SpecializesCache, find_associated_item}; |
8faf50e0 | 50 | pub use self::engine::{TraitEngine, TraitEngineExt}; |
1a4d82fc | 51 | pub use self::util::elaborate_predicates; |
1a4d82fc JJ |
52 | pub use self::util::supertraits; |
53 | pub use self::util::Supertraits; | |
c34b1796 AL |
54 | pub use self::util::supertrait_def_ids; |
55 | pub use self::util::SupertraitDefIds; | |
1a4d82fc | 56 | pub use self::util::transitive_bounds; |
1a4d82fc | 57 | |
94b46f34 XL |
58 | #[allow(dead_code)] |
59 | pub mod auto_trait; | |
1a4d82fc | 60 | mod coherence; |
0531ce1d XL |
61 | pub mod error_reporting; |
62 | mod engine; | |
1a4d82fc JJ |
63 | mod fulfill; |
64 | mod project; | |
65 | mod object_safety; | |
ea8adc8c | 66 | mod on_unimplemented; |
1a4d82fc | 67 | mod select; |
54a0048b | 68 | mod specialize; |
e9174d1e | 69 | mod structural_impls; |
94b46f34 | 70 | pub mod codegen; |
1a4d82fc JJ |
71 | mod util; |
72 | ||
0531ce1d XL |
73 | pub mod query; |
74 | ||
ff7c6d11 XL |
75 | // Whether to enable bug compatibility with issue #43355 |
76 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | |
77 | pub enum IntercrateMode { | |
78 | Issue43355, | |
79 | Fixed | |
80 | } | |
81 | ||
83c7162d XL |
82 | // The mode that trait queries run in |
83 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | |
84 | pub enum TraitQueryMode { | |
85 | // Standard/un-canonicalized queries get accurate | |
86 | // spans etc. passed in and hence can do reasonable | |
87 | // error reporting on their own. | |
88 | Standard, | |
89 | // Canonicalized queries get dummy spans and hence | |
90 | // must generally propagate errors to | |
91 | // pre-canonicalization callsites. | |
92 | Canonical, | |
93 | } | |
94 | ||
1a4d82fc JJ |
95 | /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for |
96 | /// which the vtable must be found. The process of finding a vtable is | |
97 | /// called "resolving" the `Obligation`. This process consists of | |
98 | /// either identifying an `impl` (e.g., `impl Eq for int`) that | |
99 | /// provides the required vtable, or else finding a bound that is in | |
100 | /// scope. The eventual result is usually a `Selection` (defined below). | |
0531ce1d | 101 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc | 102 | pub struct Obligation<'tcx, T> { |
0531ce1d | 103 | /// Why do we have to prove this thing? |
1a4d82fc | 104 | pub cause: ObligationCause<'tcx>, |
0531ce1d XL |
105 | |
106 | /// In which environment should we prove this thing? | |
7cac9316 | 107 | pub param_env: ty::ParamEnv<'tcx>, |
0531ce1d XL |
108 | |
109 | /// What are we trying to prove? | |
1a4d82fc | 110 | pub predicate: T, |
0531ce1d XL |
111 | |
112 | /// If we started proving this as a result of trying to prove | |
113 | /// something else, track the total depth to ensure termination. | |
114 | /// If this goes over a certain threshold, we abort compilation -- | |
115 | /// in such cases, we can not say whether or not the predicate | |
116 | /// holds for certain. Stupid halting problem. Such a drag. | |
117 | pub recursion_depth: usize, | |
1a4d82fc JJ |
118 | } |
119 | ||
120 | pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; | |
121 | pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; | |
122 | ||
123 | /// Why did we incur this obligation? Used for error reporting. | |
0531ce1d | 124 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
125 | pub struct ObligationCause<'tcx> { |
126 | pub span: Span, | |
127 | ||
128 | // The id of the fn body that triggered this obligation. This is | |
129 | // used for region obligations to determine the precise | |
130 | // environment in which the region obligation should be evaluated | |
131 | // (in particular, closures can add new assumptions). See the | |
132 | // field `region_obligations` of the `FulfillmentContext` for more | |
133 | // information. | |
134 | pub body_id: ast::NodeId, | |
135 | ||
136 | pub code: ObligationCauseCode<'tcx> | |
137 | } | |
138 | ||
2c00a5a8 XL |
139 | impl<'tcx> ObligationCause<'tcx> { |
140 | pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span { | |
141 | match self.code { | |
142 | ObligationCauseCode::CompareImplMethodObligation { .. } | | |
143 | ObligationCauseCode::MainFunctionType | | |
144 | ObligationCauseCode::StartFunctionType => { | |
145 | tcx.sess.codemap().def_span(self.span) | |
146 | } | |
147 | _ => self.span, | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
0531ce1d | 152 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
153 | pub enum ObligationCauseCode<'tcx> { |
154 | /// Not well classified or should be obvious from span. | |
155 | MiscObligation, | |
156 | ||
a7813a04 | 157 | /// A slice or array is WF only if `T: Sized` |
e9174d1e SL |
158 | SliceOrArrayElem, |
159 | ||
a7813a04 XL |
160 | /// A tuple is WF only if its middle elements are Sized |
161 | TupleElem, | |
162 | ||
e9174d1e SL |
163 | /// This is the trait reference from the given projection |
164 | ProjectionWf(ty::ProjectionTy<'tcx>), | |
165 | ||
1a4d82fc JJ |
166 | /// In an impl of trait X for type Y, type Y must |
167 | /// also implement all supertraits of X. | |
e9174d1e SL |
168 | ItemObligation(DefId), |
169 | ||
170 | /// A type like `&'a T` is WF only if `T: 'a`. | |
171 | ReferenceOutlivesReferent(Ty<'tcx>), | |
1a4d82fc | 172 | |
c30ab7b3 | 173 | /// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`. |
7cac9316 | 174 | ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>), |
c30ab7b3 | 175 | |
1a4d82fc JJ |
176 | /// Obligation incurred due to an object cast. |
177 | ObjectCastObligation(/* Object type */ Ty<'tcx>), | |
178 | ||
041b39d2 XL |
179 | // Various cases where expressions must be sized/copy/etc: |
180 | /// L = X implies that L is Sized | |
181 | AssignmentLhsSized, | |
182 | /// (x1, .., xn) must be Sized | |
183 | TupleInitializerSized, | |
184 | /// S { ... } must be Sized | |
185 | StructInitializerSized, | |
186 | /// Type of each variable must be Sized | |
187 | VariableType(ast::NodeId), | |
188 | /// Return type must be Sized | |
189 | SizedReturnType, | |
2c00a5a8 XL |
190 | /// Yield type must be Sized |
191 | SizedYieldType, | |
041b39d2 XL |
192 | /// [T,..n] --> T must be Copy |
193 | RepeatVec, | |
194 | ||
195 | /// Types of fields (other than the last) in a struct must be sized. | |
3b2f2976 | 196 | FieldSized(AdtKind), |
1a4d82fc | 197 | |
041b39d2 | 198 | /// Constant expressions must be sized. |
3157f602 XL |
199 | ConstSized, |
200 | ||
041b39d2 | 201 | /// static items must have `Sync` type |
1a4d82fc JJ |
202 | SharedStatic, |
203 | ||
204 | BuiltinDerivedObligation(DerivedObligationCause<'tcx>), | |
205 | ||
206 | ImplDerivedObligation(DerivedObligationCause<'tcx>), | |
85aaf69f | 207 | |
041b39d2 | 208 | /// error derived when matching traits/impls; see ObligationCause for more details |
c30ab7b3 SL |
209 | CompareImplMethodObligation { |
210 | item_name: ast::Name, | |
211 | impl_item_def_id: DefId, | |
212 | trait_item_def_id: DefId, | |
c30ab7b3 | 213 | }, |
476ff2be | 214 | |
041b39d2 | 215 | /// Checking that this expression can be assigned where it needs to be |
476ff2be SL |
216 | // FIXME(eddyb) #11161 is the original Expr required? |
217 | ExprAssignable, | |
218 | ||
041b39d2 | 219 | /// Computing common supertype in the arms of a match expression |
476ff2be SL |
220 | MatchExpressionArm { arm_span: Span, |
221 | source: hir::MatchSource }, | |
222 | ||
041b39d2 | 223 | /// Computing common supertype in an if expression |
476ff2be SL |
224 | IfExpression, |
225 | ||
041b39d2 | 226 | /// Computing common supertype of an if expression with no else counter-part |
476ff2be SL |
227 | IfExpressionWithNoElse, |
228 | ||
041b39d2 | 229 | /// `main` has wrong type |
476ff2be SL |
230 | MainFunctionType, |
231 | ||
041b39d2 | 232 | /// `start` has wrong type |
476ff2be SL |
233 | StartFunctionType, |
234 | ||
041b39d2 | 235 | /// intrinsic has wrong type |
476ff2be SL |
236 | IntrinsicType, |
237 | ||
041b39d2 | 238 | /// method receiver |
476ff2be | 239 | MethodReceiver, |
cc61c64b | 240 | |
041b39d2 | 241 | /// `return` with no expression |
cc61c64b | 242 | ReturnNoExpression, |
041b39d2 XL |
243 | |
244 | /// `return` with an expression | |
245 | ReturnType(ast::NodeId), | |
246 | ||
247 | /// Block implicit return | |
248 | BlockTailExpression(ast::NodeId), | |
94b46f34 XL |
249 | |
250 | /// #[feature(trivial_bounds)] is not enabled | |
251 | TrivialBound, | |
1a4d82fc JJ |
252 | } |
253 | ||
0531ce1d | 254 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
255 | pub struct DerivedObligationCause<'tcx> { |
256 | /// The trait reference of the parent obligation that led to the | |
257 | /// current obligation. Note that only trait obligations lead to | |
258 | /// derived obligations, so we just store the trait reference here | |
259 | /// directly. | |
260 | parent_trait_ref: ty::PolyTraitRef<'tcx>, | |
261 | ||
262 | /// The parent trait had this cause | |
263 | parent_code: Rc<ObligationCauseCode<'tcx>> | |
264 | } | |
265 | ||
62682a34 SL |
266 | pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>; |
267 | pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>; | |
268 | pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>; | |
1a4d82fc | 269 | |
0531ce1d | 270 | /// The following types: |
8faf50e0 XL |
271 | /// * `WhereClause` |
272 | /// * `WellFormed` | |
273 | /// * `FromEnv` | |
0531ce1d XL |
274 | /// * `DomainGoal` |
275 | /// * `Goal` | |
276 | /// * `Clause` | |
277 | /// are used for representing the trait system in the form of | |
278 | /// logic programming clauses. They are part of the interface | |
279 | /// for the chalk SLG solver. | |
280 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
8faf50e0 | 281 | pub enum WhereClause<'tcx> { |
0531ce1d XL |
282 | Implemented(ty::TraitPredicate<'tcx>), |
283 | ProjectionEq(ty::ProjectionPredicate<'tcx>), | |
8faf50e0 XL |
284 | RegionOutlives(ty::RegionOutlivesPredicate<'tcx>), |
285 | TypeOutlives(ty::TypeOutlivesPredicate<'tcx>), | |
286 | } | |
287 | ||
288 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
289 | pub enum WellFormed<'tcx> { | |
290 | Trait(ty::TraitPredicate<'tcx>), | |
291 | Ty(Ty<'tcx>), | |
292 | } | |
293 | ||
294 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
295 | pub enum FromEnv<'tcx> { | |
296 | Trait(ty::TraitPredicate<'tcx>), | |
297 | Ty(Ty<'tcx>), | |
0531ce1d XL |
298 | } |
299 | ||
300 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
301 | pub enum DomainGoal<'tcx> { | |
8faf50e0 XL |
302 | Holds(WhereClause<'tcx>), |
303 | WellFormed(WellFormed<'tcx>), | |
304 | FromEnv(FromEnv<'tcx>), | |
83c7162d | 305 | Normalize(ty::ProjectionPredicate<'tcx>), |
0531ce1d XL |
306 | } |
307 | ||
83c7162d XL |
308 | pub type PolyDomainGoal<'tcx> = ty::Binder<DomainGoal<'tcx>>; |
309 | ||
0531ce1d XL |
310 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
311 | pub enum QuantifierKind { | |
312 | Universal, | |
313 | Existential, | |
314 | } | |
315 | ||
83c7162d | 316 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
0531ce1d | 317 | pub enum Goal<'tcx> { |
83c7162d XL |
318 | Implies(Clauses<'tcx>, &'tcx Goal<'tcx>), |
319 | And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>), | |
320 | Not(&'tcx Goal<'tcx>), | |
0531ce1d | 321 | DomainGoal(DomainGoal<'tcx>), |
83c7162d XL |
322 | Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>), |
323 | CannotProve, | |
0531ce1d XL |
324 | } |
325 | ||
83c7162d XL |
326 | pub type Goals<'tcx> = &'tcx Slice<Goal<'tcx>>; |
327 | ||
8faf50e0 XL |
328 | impl<'tcx> DomainGoal<'tcx> { |
329 | pub fn into_goal(self) -> Goal<'tcx> { | |
330 | Goal::DomainGoal(self) | |
331 | } | |
332 | } | |
333 | ||
83c7162d XL |
334 | impl<'tcx> Goal<'tcx> { |
335 | pub fn from_poly_domain_goal<'a>( | |
336 | domain_goal: PolyDomainGoal<'tcx>, | |
337 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
338 | ) -> Goal<'tcx> { | |
339 | match domain_goal.no_late_bound_regions() { | |
8faf50e0 | 340 | Some(p) => p.into_goal(), |
83c7162d XL |
341 | None => Goal::Quantified( |
342 | QuantifierKind::Universal, | |
8faf50e0 | 343 | domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal())) |
83c7162d XL |
344 | ), |
345 | } | |
0531ce1d XL |
346 | } |
347 | } | |
348 | ||
0531ce1d XL |
349 | /// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary |
350 | /// Harrop Formulas". | |
83c7162d | 351 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
0531ce1d | 352 | pub enum Clause<'tcx> { |
83c7162d XL |
353 | Implies(ProgramClause<'tcx>), |
354 | ForAll(ty::Binder<ProgramClause<'tcx>>), | |
355 | } | |
356 | ||
357 | /// Multiple clauses. | |
358 | pub type Clauses<'tcx> = &'tcx Slice<Clause<'tcx>>; | |
359 | ||
360 | /// A "program clause" has the form `D :- G1, ..., Gn`. It is saying | |
361 | /// that the domain goal `D` is true if `G1...Gn` are provable. This | |
362 | /// is equivalent to the implication `G1..Gn => D`; we usually write | |
363 | /// it with the reverse implication operator `:-` to emphasize the way | |
364 | /// that programs are actually solved (via backchaining, which starts | |
365 | /// with the goal to solve and proceeds from there). | |
366 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | |
367 | pub struct ProgramClause<'tcx> { | |
368 | /// This goal will be considered true... | |
369 | pub goal: DomainGoal<'tcx>, | |
370 | ||
371 | /// ...if we can prove these hypotheses (there may be no hypotheses at all): | |
372 | pub hypotheses: Goals<'tcx>, | |
0531ce1d XL |
373 | } |
374 | ||
1a4d82fc JJ |
375 | pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; |
376 | ||
85aaf69f | 377 | #[derive(Clone,Debug)] |
1a4d82fc JJ |
378 | pub enum SelectionError<'tcx> { |
379 | Unimplemented, | |
1a4d82fc JJ |
380 | OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>, |
381 | ty::PolyTraitRef<'tcx>, | |
e9174d1e SL |
382 | ty::error::TypeError<'tcx>), |
383 | TraitNotObjectSafe(DefId), | |
8faf50e0 | 384 | ConstEvalFailure(Lrc<ConstEvalErr<'tcx>>), |
83c7162d | 385 | Overflow, |
1a4d82fc JJ |
386 | } |
387 | ||
388 | pub struct FulfillmentError<'tcx> { | |
389 | pub obligation: PredicateObligation<'tcx>, | |
390 | pub code: FulfillmentErrorCode<'tcx> | |
391 | } | |
392 | ||
393 | #[derive(Clone)] | |
394 | pub enum FulfillmentErrorCode<'tcx> { | |
395 | CodeSelectionError(SelectionError<'tcx>), | |
396 | CodeProjectionError(MismatchedProjectionTypes<'tcx>), | |
cc61c64b XL |
397 | CodeSubtypeError(ExpectedFound<Ty<'tcx>>, |
398 | TypeError<'tcx>), // always comes from a SubtypePredicate | |
1a4d82fc JJ |
399 | CodeAmbiguity, |
400 | } | |
401 | ||
402 | /// When performing resolution, it is typically the case that there | |
403 | /// can be one of three outcomes: | |
404 | /// | |
405 | /// - `Ok(Some(r))`: success occurred with result `r` | |
406 | /// - `Ok(None)`: could not definitely determine anything, usually due | |
407 | /// to inconclusive type inference. | |
408 | /// - `Err(e)`: error `e` occurred | |
409 | pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>; | |
410 | ||
411 | /// Given the successful resolution of an obligation, the `Vtable` | |
412 | /// indicates where the vtable comes from. Note that while we call this | |
413 | /// a "vtable", it does not necessarily indicate dynamic dispatch at | |
414 | /// runtime. `Vtable` instances just tell the compiler where to find | |
415 | /// methods, but in generic code those methods are typically statically | |
416 | /// dispatched -- only when an object is constructed is a `Vtable` | |
417 | /// instance reified into an actual vtable. | |
418 | /// | |
419 | /// For example, the vtable may be tied to a specific impl (case A), | |
420 | /// or it may be relative to some bound that is in scope (case B). | |
421 | /// | |
422 | /// | |
423 | /// ``` | |
424 | /// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1 | |
425 | /// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2 | |
426 | /// impl Clone for int { ... } // Impl_3 | |
427 | /// | |
428 | /// fn foo<T:Clone>(concrete: Option<Box<int>>, | |
429 | /// param: T, | |
430 | /// mixed: Option<T>) { | |
431 | /// | |
432 | /// // Case A: Vtable points at a specific impl. Only possible when | |
433 | /// // type is concretely known. If the impl itself has bounded | |
434 | /// // type parameters, Vtable will carry resolutions for those as well: | |
435 | /// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])]) | |
436 | /// | |
437 | /// // Case B: Vtable must be provided by caller. This applies when | |
438 | /// // type is a type parameter. | |
439 | /// param.clone(); // VtableParam | |
440 | /// | |
441 | /// // Case C: A mix of cases A and B. | |
442 | /// mixed.clone(); // Vtable(Impl_1, [VtableParam]) | |
443 | /// } | |
444 | /// ``` | |
445 | /// | |
446 | /// ### The type parameter `N` | |
447 | /// | |
448 | /// See explanation on `VtableImplData`. | |
0531ce1d | 449 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
1a4d82fc JJ |
450 | pub enum Vtable<'tcx, N> { |
451 | /// Vtable identifying a particular impl. | |
452 | VtableImpl(VtableImplData<'tcx, N>), | |
453 | ||
abe05a73 | 454 | /// Vtable for auto trait implementations |
c34b1796 | 455 | /// This carries the information and nested obligations with regards |
abe05a73 | 456 | /// to an auto implementation for a trait `Trait`. The nested obligations |
c34b1796 | 457 | /// ensure the trait implementation holds for all the constituent types. |
abe05a73 | 458 | VtableAutoImpl(VtableAutoImplData<N>), |
c34b1796 | 459 | |
1a4d82fc | 460 | /// Successful resolution to an obligation provided by the caller |
85aaf69f SL |
461 | /// for some type parameter. The `Vec<N>` represents the |
462 | /// obligations incurred from normalizing the where-clause (if | |
463 | /// any). | |
464 | VtableParam(Vec<N>), | |
1a4d82fc JJ |
465 | |
466 | /// Virtual calls through an object | |
a7813a04 | 467 | VtableObject(VtableObjectData<'tcx, N>), |
1a4d82fc JJ |
468 | |
469 | /// Successful resolution for a builtin trait. | |
470 | VtableBuiltin(VtableBuiltinData<N>), | |
471 | ||
85aaf69f SL |
472 | /// Vtable automatically generated for a closure. The def ID is the ID |
473 | /// of the closure expression. This is a `VtableImpl` in spirit, but the | |
474 | /// impl is generated by the compiler and does not appear in the source. | |
62682a34 | 475 | VtableClosure(VtableClosureData<'tcx, N>), |
1a4d82fc JJ |
476 | |
477 | /// Same as above, but for a fn pointer type with the given signature. | |
a7813a04 | 478 | VtableFnPointer(VtableFnPointerData<'tcx, N>), |
ea8adc8c XL |
479 | |
480 | /// Vtable automatically generated for a generator | |
481 | VtableGenerator(VtableGeneratorData<'tcx, N>), | |
1a4d82fc JJ |
482 | } |
483 | ||
484 | /// Identifies a particular impl in the source, along with a set of | |
485 | /// substitutions from the impl's type/lifetime parameters. The | |
486 | /// `nested` vector corresponds to the nested obligations attached to | |
487 | /// the impl's type parameters. | |
488 | /// | |
489 | /// The type parameter `N` indicates the type used for "nested | |
490 | /// obligations" that are required by the impl. During type check, this | |
94b46f34 XL |
491 | /// is `Obligation`, as one might expect. During codegen, however, this |
492 | /// is `()`, because codegen only requires a shallow resolution of an | |
1a4d82fc | 493 | /// impl, and nested obligations are satisfied later. |
ff7c6d11 | 494 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
1a4d82fc | 495 | pub struct VtableImplData<'tcx, N> { |
e9174d1e | 496 | pub impl_def_id: DefId, |
9e0c209e | 497 | pub substs: &'tcx Substs<'tcx>, |
62682a34 SL |
498 | pub nested: Vec<N> |
499 | } | |
500 | ||
ff7c6d11 | 501 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
ea8adc8c | 502 | pub struct VtableGeneratorData<'tcx, N> { |
94b46f34 XL |
503 | pub generator_def_id: DefId, |
504 | pub substs: ty::GeneratorSubsts<'tcx>, | |
ea8adc8c XL |
505 | /// Nested obligations. This can be non-empty if the generator |
506 | /// signature contains associated types. | |
507 | pub nested: Vec<N> | |
508 | } | |
509 | ||
ff7c6d11 | 510 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
62682a34 | 511 | pub struct VtableClosureData<'tcx, N> { |
e9174d1e | 512 | pub closure_def_id: DefId, |
c1a9b12d | 513 | pub substs: ty::ClosureSubsts<'tcx>, |
62682a34 SL |
514 | /// Nested obligations. This can be non-empty if the closure |
515 | /// signature contains associated types. | |
516 | pub nested: Vec<N> | |
1a4d82fc JJ |
517 | } |
518 | ||
0531ce1d | 519 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
abe05a73 | 520 | pub struct VtableAutoImplData<N> { |
e9174d1e | 521 | pub trait_def_id: DefId, |
c34b1796 AL |
522 | pub nested: Vec<N> |
523 | } | |
524 | ||
0531ce1d | 525 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
1a4d82fc | 526 | pub struct VtableBuiltinData<N> { |
62682a34 | 527 | pub nested: Vec<N> |
1a4d82fc JJ |
528 | } |
529 | ||
530 | /// A vtable for some object-safe trait `Foo` automatically derived | |
531 | /// for the object type `Foo`. | |
ff7c6d11 | 532 | #[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] |
a7813a04 | 533 | pub struct VtableObjectData<'tcx, N> { |
c34b1796 AL |
534 | /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. |
535 | pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, | |
c1a9b12d SL |
536 | |
537 | /// The vtable is formed by concatenating together the method lists of | |
538 | /// the base object trait and all supertraits; this is the start of | |
539 | /// `upcast_trait_ref`'s methods in that vtable. | |
a7813a04 XL |
540 | pub vtable_base: usize, |
541 | ||
542 | pub nested: Vec<N>, | |
543 | } | |
544 | ||
ff7c6d11 | 545 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
a7813a04 | 546 | pub struct VtableFnPointerData<'tcx, N> { |
ea8adc8c | 547 | pub fn_ty: Ty<'tcx>, |
a7813a04 | 548 | pub nested: Vec<N> |
1a4d82fc JJ |
549 | } |
550 | ||
1a4d82fc | 551 | /// Creates predicate obligations from the generic bounds. |
62682a34 | 552 | pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, |
7cac9316 | 553 | param_env: ty::ParamEnv<'tcx>, |
85aaf69f | 554 | generic_bounds: &ty::InstantiatedPredicates<'tcx>) |
1a4d82fc JJ |
555 | -> PredicateObligations<'tcx> |
556 | { | |
7cac9316 | 557 | util::predicates_for_generics(cause, 0, param_env, generic_bounds) |
1a4d82fc JJ |
558 | } |
559 | ||
560 | /// Determines whether the type `ty` is known to meet `bound` and | |
561 | /// returns true if so. Returns false if `ty` either does not meet | |
562 | /// `bound` or is not known to meet bound (note that this is | |
563 | /// conservative towards *no impl*, which is the opposite of the | |
564 | /// `evaluate` methods). | |
476ff2be | 565 | pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, |
7cac9316 | 566 | param_env: ty::ParamEnv<'tcx>, |
476ff2be SL |
567 | ty: Ty<'tcx>, |
568 | def_id: DefId, | |
569 | span: Span) | |
570 | -> bool | |
1a4d82fc | 571 | { |
476ff2be | 572 | debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", |
62682a34 | 573 | ty, |
476ff2be SL |
574 | infcx.tcx.item_path_str(def_id)); |
575 | ||
576 | let trait_ref = ty::TraitRef { | |
041b39d2 | 577 | def_id, |
476ff2be | 578 | substs: infcx.tcx.mk_substs_trait(ty, &[]), |
92a42be0 | 579 | }; |
476ff2be | 580 | let obligation = Obligation { |
7cac9316 | 581 | param_env, |
476ff2be SL |
582 | cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID), |
583 | recursion_depth: 0, | |
584 | predicate: trait_ref.to_predicate(), | |
585 | }; | |
586 | ||
83c7162d | 587 | let result = infcx.predicate_must_hold(&obligation); |
476ff2be SL |
588 | debug!("type_known_to_meet_ty={:?} bound={} => {:?}", |
589 | ty, infcx.tcx.item_path_str(def_id), result); | |
92a42be0 SL |
590 | |
591 | if result && (ty.has_infer_types() || ty.has_closure_types()) { | |
592 | // Because of inference "guessing", selection can sometimes claim | |
593 | // to succeed while the success requires a guess. To ensure | |
594 | // this function's result remains infallible, we must confirm | |
595 | // that guess. While imperfect, I believe this is sound. | |
596 | ||
ff7c6d11 XL |
597 | // The handling of regions in this area of the code is terrible, |
598 | // see issue #29149. We should be able to improve on this with | |
599 | // NLL. | |
600 | let mut fulfill_cx = FulfillmentContext::new_ignoring_regions(); | |
92a42be0 SL |
601 | |
602 | // We can use a dummy node-id here because we won't pay any mind | |
603 | // to region obligations that arise (there shouldn't really be any | |
604 | // anyhow). | |
605 | let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); | |
606 | ||
7cac9316 | 607 | fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause); |
92a42be0 SL |
608 | |
609 | // Note: we only assume something is `Copy` if we can | |
610 | // *definitively* show that it implements `Copy`. Otherwise, | |
611 | // assume it is move; linear is always ok. | |
612 | match fulfill_cx.select_all_or_error(infcx) { | |
613 | Ok(()) => { | |
476ff2be | 614 | debug!("type_known_to_meet_bound: ty={:?} bound={} success", |
92a42be0 | 615 | ty, |
476ff2be | 616 | infcx.tcx.item_path_str(def_id)); |
92a42be0 SL |
617 | true |
618 | } | |
619 | Err(e) => { | |
476ff2be | 620 | debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}", |
92a42be0 | 621 | ty, |
476ff2be | 622 | infcx.tcx.item_path_str(def_id), |
92a42be0 SL |
623 | e); |
624 | false | |
625 | } | |
1a4d82fc | 626 | } |
92a42be0 SL |
627 | } else { |
628 | result | |
1a4d82fc JJ |
629 | } |
630 | } | |
631 | ||
c1a9b12d | 632 | // FIXME: this is gonna need to be removed ... |
c34b1796 | 633 | /// Normalizes the parameter environment, reporting errors if they occur. |
a7813a04 | 634 | pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
7cac9316 XL |
635 | region_context: DefId, |
636 | unnormalized_env: ty::ParamEnv<'tcx>, | |
637 | cause: ObligationCause<'tcx>) | |
638 | -> ty::ParamEnv<'tcx> | |
85aaf69f | 639 | { |
c34b1796 AL |
640 | // I'm not wild about reporting errors here; I'd prefer to |
641 | // have the errors get reported at a defined place (e.g., | |
642 | // during typeck). Instead I have all parameter | |
643 | // environments, in effect, going through this function | |
644 | // and hence potentially reporting errors. This ensurse of | |
645 | // course that we never forget to normalize (the | |
646 | // alternative seemed like it would involve a lot of | |
647 | // manual invocations of this fn -- and then we'd have to | |
648 | // deal with the errors at each of those sites). | |
649 | // | |
650 | // In any case, in practice, typeck constructs all the | |
651 | // parameter environments once for every fn as it goes, | |
652 | // and errors will get reported then; so after typeck we | |
653 | // can be sure that no errors should occur. | |
654 | ||
c34b1796 | 655 | let span = cause.span; |
c34b1796 | 656 | |
62682a34 SL |
657 | debug!("normalize_param_env_or_error(unnormalized_env={:?})", |
658 | unnormalized_env); | |
659 | ||
660 | let predicates: Vec<_> = | |
7cac9316 | 661 | util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) |
62682a34 SL |
662 | .collect(); |
663 | ||
62682a34 SL |
664 | debug!("normalize_param_env_or_error: elaborated-predicates={:?}", |
665 | predicates); | |
666 | ||
7cac9316 XL |
667 | let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), |
668 | unnormalized_env.reveal); | |
669 | ||
041b39d2 | 670 | tcx.infer_ctxt().enter(|infcx| { |
ff7c6d11 XL |
671 | // FIXME. We should really... do something with these region |
672 | // obligations. But this call just continues the older | |
673 | // behavior (i.e., doesn't cause any new bugs), and it would | |
674 | // take some further refactoring to actually solve them. In | |
675 | // particular, we would have to handle implied bounds | |
676 | // properly, and that code is currently largely confined to | |
677 | // regionck (though I made some efforts to extract it | |
678 | // out). -nmatsakis | |
679 | // | |
680 | // @arielby: In any case, these obligations are checked | |
681 | // by wfcheck anyway, so I'm not sure we have to check | |
682 | // them here too, and we will remove this function when | |
683 | // we move over to lazy normalization *anyway*. | |
684 | let fulfill_cx = FulfillmentContext::new_ignoring_regions(); | |
685 | ||
94b46f34 | 686 | let predicates = match fully_normalize( |
7cac9316 | 687 | &infcx, |
ff7c6d11 | 688 | fulfill_cx, |
7cac9316 XL |
689 | cause, |
690 | elaborated_env, | |
691 | // You would really want to pass infcx.param_env.caller_bounds here, | |
692 | // but that is an interned slice, and fully_normalize takes &T and returns T, so | |
693 | // without further refactoring, a slice can't be used. Luckily, we still have the | |
694 | // predicate vector from which we created the ParamEnv in infcx, so we | |
695 | // can pass that instead. It's roundabout and a bit brittle, but this code path | |
696 | // ought to be refactored anyway, and until then it saves us from having to copy. | |
697 | &predicates, | |
698 | ) { | |
a7813a04 XL |
699 | Ok(predicates) => predicates, |
700 | Err(errors) => { | |
0531ce1d | 701 | infcx.report_fulfillment_errors(&errors, None, false); |
a7813a04 | 702 | // An unnormalized env is better than nothing. |
7cac9316 | 703 | return elaborated_env; |
a7813a04 XL |
704 | } |
705 | }; | |
706 | ||
707 | debug!("normalize_param_env_or_error: normalized predicates={:?}", | |
708 | predicates); | |
709 | ||
ea8adc8c | 710 | let region_scope_tree = region::ScopeTree::default(); |
abe05a73 | 711 | |
ff7c6d11 XL |
712 | // We can use the `elaborated_env` here; the region code only |
713 | // cares about declarations like `'a: 'b`. | |
714 | let outlives_env = OutlivesEnvironment::new(elaborated_env); | |
715 | ||
716 | infcx.resolve_regions_and_report_errors(region_context, ®ion_scope_tree, &outlives_env); | |
abe05a73 | 717 | |
a7813a04 XL |
718 | let predicates = match infcx.fully_resolve(&predicates) { |
719 | Ok(predicates) => predicates, | |
720 | Err(fixup_err) => { | |
721 | // If we encounter a fixup error, it means that some type | |
722 | // variable wound up unconstrained. I actually don't know | |
723 | // if this can happen, and I certainly don't expect it to | |
724 | // happen often, but if it did happen it probably | |
725 | // represents a legitimate failure due to some kind of | |
726 | // unconstrained variable, and it seems better not to ICE, | |
727 | // all things considered. | |
728 | tcx.sess.span_err(span, &fixup_err.to_string()); | |
729 | // An unnormalized env is better than nothing. | |
7cac9316 | 730 | return elaborated_env; |
a7813a04 XL |
731 | } |
732 | }; | |
7453a54e | 733 | |
a7813a04 XL |
734 | let predicates = match tcx.lift_to_global(&predicates) { |
735 | Some(predicates) => predicates, | |
7cac9316 | 736 | None => return elaborated_env, |
a7813a04 | 737 | }; |
85aaf69f | 738 | |
a7813a04 | 739 | debug!("normalize_param_env_or_error: resolved predicates={:?}", |
7cac9316 | 740 | predicates); |
7453a54e | 741 | |
7cac9316 | 742 | ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal) |
a7813a04 | 743 | }) |
85aaf69f SL |
744 | } |
745 | ||
94b46f34 | 746 | pub fn fully_normalize<'a, 'gcx, 'tcx, T>( |
ff7c6d11 XL |
747 | infcx: &InferCtxt<'a, 'gcx, 'tcx>, |
748 | mut fulfill_cx: FulfillmentContext<'tcx>, | |
749 | cause: ObligationCause<'tcx>, | |
750 | param_env: ty::ParamEnv<'tcx>, | |
751 | value: &T) | |
752 | -> Result<T, Vec<FulfillmentError<'tcx>>> | |
753 | where T : TypeFoldable<'tcx> | |
754 | { | |
755 | debug!("fully_normalize_with_fulfillcx(value={:?})", value); | |
756 | let selcx = &mut SelectionContext::new(infcx); | |
85aaf69f | 757 | let Normalized { value: normalized_value, obligations } = |
7cac9316 | 758 | project::normalize(selcx, param_env, cause, value); |
7453a54e | 759 | debug!("fully_normalize: normalized_value={:?} obligations={:?}", |
62682a34 SL |
760 | normalized_value, |
761 | obligations); | |
85aaf69f SL |
762 | for obligation in obligations { |
763 | fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation); | |
764 | } | |
c1a9b12d | 765 | |
7453a54e | 766 | debug!("fully_normalize: select_all_or_error start"); |
94b46f34 | 767 | fulfill_cx.select_all_or_error(infcx)?; |
7453a54e | 768 | debug!("fully_normalize: select_all_or_error complete"); |
85aaf69f | 769 | let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value); |
7453a54e | 770 | debug!("fully_normalize: resolved_value={:?}", resolved_value); |
85aaf69f SL |
771 | Ok(resolved_value) |
772 | } | |
773 | ||
7cac9316 XL |
774 | /// Normalizes the predicates and checks whether they hold in an empty |
775 | /// environment. If this returns false, then either normalize | |
776 | /// encountered an error or one of the predicates did not hold. Used | |
777 | /// when creating vtables to check for unsatisfiable methods. | |
2c00a5a8 XL |
778 | fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
779 | predicates: Vec<ty::Predicate<'tcx>>) | |
780 | -> bool | |
9e0c209e SL |
781 | { |
782 | debug!("normalize_and_test_predicates(predicates={:?})", | |
783 | predicates); | |
784 | ||
041b39d2 | 785 | let result = tcx.infer_ctxt().enter(|infcx| { |
0531ce1d | 786 | let param_env = ty::ParamEnv::reveal_all(); |
9e0c209e SL |
787 | let mut selcx = SelectionContext::new(&infcx); |
788 | let mut fulfill_cx = FulfillmentContext::new(); | |
789 | let cause = ObligationCause::dummy(); | |
790 | let Normalized { value: predicates, obligations } = | |
7cac9316 | 791 | normalize(&mut selcx, param_env, cause.clone(), &predicates); |
9e0c209e SL |
792 | for obligation in obligations { |
793 | fulfill_cx.register_predicate_obligation(&infcx, obligation); | |
794 | } | |
795 | for predicate in predicates { | |
7cac9316 | 796 | let obligation = Obligation::new(cause.clone(), param_env, predicate); |
9e0c209e SL |
797 | fulfill_cx.register_predicate_obligation(&infcx, obligation); |
798 | } | |
799 | ||
800 | fulfill_cx.select_all_or_error(&infcx).is_ok() | |
041b39d2 XL |
801 | }); |
802 | debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", | |
803 | predicates, result); | |
804 | result | |
9e0c209e SL |
805 | } |
806 | ||
2c00a5a8 XL |
807 | fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
808 | key: (DefId, &'tcx Substs<'tcx>)) | |
809 | -> bool | |
810 | { | |
811 | use ty::subst::Subst; | |
812 | debug!("substitute_normalize_and_test_predicates(key={:?})", | |
813 | key); | |
814 | ||
815 | let predicates = tcx.predicates_of(key.0).predicates.subst(tcx, key.1); | |
816 | let result = normalize_and_test_predicates(tcx, predicates); | |
817 | ||
818 | debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", | |
819 | key, result); | |
820 | result | |
821 | } | |
822 | ||
9e0c209e SL |
823 | /// Given a trait `trait_ref`, iterates the vtable entries |
824 | /// that come from `trait_ref`, including its supertraits. | |
825 | #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. | |
abe05a73 | 826 | fn vtable_methods<'a, 'tcx>( |
9e0c209e SL |
827 | tcx: TyCtxt<'a, 'tcx, 'tcx>, |
828 | trait_ref: ty::PolyTraitRef<'tcx>) | |
0531ce1d | 829 | -> Lrc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>> |
9e0c209e | 830 | { |
abe05a73 XL |
831 | debug!("vtable_methods({:?})", trait_ref); |
832 | ||
0531ce1d | 833 | Lrc::new( |
abe05a73 XL |
834 | supertraits(tcx, trait_ref).flat_map(move |trait_ref| { |
835 | let trait_methods = tcx.associated_items(trait_ref.def_id()) | |
836 | .filter(|item| item.kind == ty::AssociatedKind::Method); | |
837 | ||
838 | // Now list each method's DefId and Substs (for within its trait). | |
839 | // If the method can never be called from this object, produce None. | |
840 | trait_methods.map(move |trait_method| { | |
841 | debug!("vtable_methods: trait_method={:?}", trait_method); | |
842 | let def_id = trait_method.def_id; | |
843 | ||
844 | // Some methods cannot be called on an object; skip those. | |
845 | if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { | |
846 | debug!("vtable_methods: not vtable safe"); | |
847 | return None; | |
848 | } | |
849 | ||
850 | // the method may have some early-bound lifetimes, add | |
851 | // regions for those | |
83c7162d | 852 | let substs = trait_ref.map_bound(|trait_ref| { |
94b46f34 XL |
853 | Substs::for_item(tcx, def_id, |param, _| { |
854 | match param.kind { | |
855 | GenericParamDefKind::Lifetime => tcx.types.re_erased.into(), | |
856 | GenericParamDefKind::Type {..} => { | |
857 | trait_ref.substs[param.index as usize] | |
858 | } | |
859 | } | |
860 | }) | |
83c7162d | 861 | }); |
abe05a73 XL |
862 | |
863 | // the trait type may have higher-ranked lifetimes in it; | |
864 | // so erase them if they appear, so that we get the type | |
865 | // at some particular call site | |
0531ce1d XL |
866 | let substs = tcx.normalize_erasing_late_bound_regions( |
867 | ty::ParamEnv::reveal_all(), | |
83c7162d | 868 | &substs |
0531ce1d | 869 | ); |
abe05a73 XL |
870 | |
871 | // It's possible that the method relies on where clauses that | |
872 | // do not hold for this particular set of type parameters. | |
873 | // Note that this method could then never be called, so we | |
94b46f34 | 874 | // do not want to try and codegen it, in that case (see #23435). |
abe05a73 XL |
875 | let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); |
876 | if !normalize_and_test_predicates(tcx, predicates.predicates) { | |
877 | debug!("vtable_methods: predicates do not hold"); | |
878 | return None; | |
879 | } | |
880 | ||
881 | Some((def_id, substs)) | |
882 | }) | |
883 | }).collect() | |
884 | ) | |
9e0c209e SL |
885 | } |
886 | ||
1a4d82fc JJ |
887 | impl<'tcx,O> Obligation<'tcx,O> { |
888 | pub fn new(cause: ObligationCause<'tcx>, | |
7cac9316 XL |
889 | param_env: ty::ParamEnv<'tcx>, |
890 | predicate: O) | |
1a4d82fc JJ |
891 | -> Obligation<'tcx, O> |
892 | { | |
7cac9316 | 893 | Obligation { cause, param_env, recursion_depth: 0, predicate } |
1a4d82fc JJ |
894 | } |
895 | ||
896 | fn with_depth(cause: ObligationCause<'tcx>, | |
c34b1796 | 897 | recursion_depth: usize, |
7cac9316 XL |
898 | param_env: ty::ParamEnv<'tcx>, |
899 | predicate: O) | |
1a4d82fc JJ |
900 | -> Obligation<'tcx, O> |
901 | { | |
7cac9316 | 902 | Obligation { cause, param_env, recursion_depth, predicate } |
1a4d82fc JJ |
903 | } |
904 | ||
7cac9316 XL |
905 | pub fn misc(span: Span, |
906 | body_id: ast::NodeId, | |
907 | param_env: ty::ParamEnv<'tcx>, | |
908 | trait_ref: O) | |
909 | -> Obligation<'tcx, O> { | |
910 | Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref) | |
1a4d82fc JJ |
911 | } |
912 | ||
913 | pub fn with<P>(&self, value: P) -> Obligation<'tcx,P> { | |
914 | Obligation { cause: self.cause.clone(), | |
7cac9316 | 915 | param_env: self.param_env, |
1a4d82fc JJ |
916 | recursion_depth: self.recursion_depth, |
917 | predicate: value } | |
918 | } | |
919 | } | |
920 | ||
921 | impl<'tcx> ObligationCause<'tcx> { | |
922 | pub fn new(span: Span, | |
923 | body_id: ast::NodeId, | |
924 | code: ObligationCauseCode<'tcx>) | |
925 | -> ObligationCause<'tcx> { | |
926 | ObligationCause { span: span, body_id: body_id, code: code } | |
927 | } | |
928 | ||
929 | pub fn misc(span: Span, body_id: ast::NodeId) -> ObligationCause<'tcx> { | |
930 | ObligationCause { span: span, body_id: body_id, code: MiscObligation } | |
931 | } | |
932 | ||
933 | pub fn dummy() -> ObligationCause<'tcx> { | |
9e0c209e | 934 | ObligationCause { span: DUMMY_SP, body_id: ast::CRATE_NODE_ID, code: MiscObligation } |
1a4d82fc JJ |
935 | } |
936 | } | |
937 | ||
938 | impl<'tcx, N> Vtable<'tcx, N> { | |
62682a34 | 939 | pub fn nested_obligations(self) -> Vec<N> { |
1a4d82fc | 940 | match self { |
62682a34 SL |
941 | VtableImpl(i) => i.nested, |
942 | VtableParam(n) => n, | |
943 | VtableBuiltin(i) => i.nested, | |
abe05a73 | 944 | VtableAutoImpl(d) => d.nested, |
62682a34 | 945 | VtableClosure(c) => c.nested, |
ea8adc8c | 946 | VtableGenerator(c) => c.nested, |
a7813a04 XL |
947 | VtableObject(d) => d.nested, |
948 | VtableFnPointer(d) => d.nested, | |
949 | } | |
950 | } | |
951 | ||
62682a34 SL |
952 | pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M { |
953 | match self { | |
954 | VtableImpl(i) => VtableImpl(VtableImplData { | |
955 | impl_def_id: i.impl_def_id, | |
956 | substs: i.substs, | |
a7813a04 | 957 | nested: i.nested.into_iter().map(f).collect(), |
62682a34 SL |
958 | }), |
959 | VtableParam(n) => VtableParam(n.into_iter().map(f).collect()), | |
960 | VtableBuiltin(i) => VtableBuiltin(VtableBuiltinData { | |
a7813a04 XL |
961 | nested: i.nested.into_iter().map(f).collect(), |
962 | }), | |
963 | VtableObject(o) => VtableObject(VtableObjectData { | |
964 | upcast_trait_ref: o.upcast_trait_ref, | |
965 | vtable_base: o.vtable_base, | |
966 | nested: o.nested.into_iter().map(f).collect(), | |
62682a34 | 967 | }), |
abe05a73 | 968 | VtableAutoImpl(d) => VtableAutoImpl(VtableAutoImplData { |
62682a34 | 969 | trait_def_id: d.trait_def_id, |
a7813a04 XL |
970 | nested: d.nested.into_iter().map(f).collect(), |
971 | }), | |
972 | VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData { | |
973 | fn_ty: p.fn_ty, | |
974 | nested: p.nested.into_iter().map(f).collect(), | |
62682a34 | 975 | }), |
ea8adc8c | 976 | VtableGenerator(c) => VtableGenerator(VtableGeneratorData { |
94b46f34 | 977 | generator_def_id: c.generator_def_id, |
ea8adc8c XL |
978 | substs: c.substs, |
979 | nested: c.nested.into_iter().map(f).collect(), | |
980 | }), | |
62682a34 SL |
981 | VtableClosure(c) => VtableClosure(VtableClosureData { |
982 | closure_def_id: c.closure_def_id, | |
983 | substs: c.substs, | |
c1a9b12d | 984 | nested: c.nested.into_iter().map(f).collect(), |
62682a34 | 985 | }) |
1a4d82fc JJ |
986 | } |
987 | } | |
988 | } | |
989 | ||
990 | impl<'tcx> FulfillmentError<'tcx> { | |
991 | fn new(obligation: PredicateObligation<'tcx>, | |
992 | code: FulfillmentErrorCode<'tcx>) | |
993 | -> FulfillmentError<'tcx> | |
994 | { | |
995 | FulfillmentError { obligation: obligation, code: code } | |
996 | } | |
1a4d82fc JJ |
997 | } |
998 | ||
999 | impl<'tcx> TraitObligation<'tcx> { | |
c34b1796 | 1000 | fn self_ty(&self) -> ty::Binder<Ty<'tcx>> { |
83c7162d | 1001 | self.predicate.map_bound(|p| p.self_ty()) |
1a4d82fc JJ |
1002 | } |
1003 | } | |
7cac9316 | 1004 | |
94b46f34 XL |
1005 | pub fn provide(providers: &mut ty::query::Providers) { |
1006 | *providers = ty::query::Providers { | |
7cac9316 XL |
1007 | is_object_safe: object_safety::is_object_safe_provider, |
1008 | specialization_graph_of: specialize::specialization_graph_provider, | |
ea8adc8c | 1009 | specializes: specialize::specializes, |
94b46f34 | 1010 | codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, |
abe05a73 | 1011 | vtable_methods, |
2c00a5a8 | 1012 | substitute_normalize_and_test_predicates, |
7cac9316 XL |
1013 | ..*providers |
1014 | }; | |
1015 | } | |
94b46f34 | 1016 | |
94b46f34 XL |
1017 | pub trait ExClauseFold<'tcx> |
1018 | where | |
1019 | Self: chalk_engine::context::Context + Clone, | |
1020 | { | |
1021 | fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>( | |
1022 | ex_clause: &chalk_engine::ExClause<Self>, | |
1023 | folder: &mut F, | |
1024 | ) -> chalk_engine::ExClause<Self>; | |
1025 | ||
1026 | fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>( | |
1027 | ex_clause: &chalk_engine::ExClause<Self>, | |
1028 | visitor: &mut V, | |
1029 | ) -> bool; | |
1030 | } | |
1031 | ||
1032 | pub trait ExClauseLift<'tcx> | |
1033 | where | |
1034 | Self: chalk_engine::context::Context + Clone, | |
1035 | { | |
1036 | type LiftedExClause: Debug + 'tcx; | |
1037 | ||
1038 | fn lift_ex_clause_to_tcx<'a, 'gcx>( | |
1039 | ex_clause: &chalk_engine::ExClause<Self>, | |
1040 | tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
1041 | ) -> Option<Self::LiftedExClause>; | |
1042 | } |