]>
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 | ||
85aaf69f | 11 | //! Trait Resolution. See the Book for more. |
1a4d82fc JJ |
12 | |
13 | pub use self::SelectionError::*; | |
14 | pub use self::FulfillmentErrorCode::*; | |
15 | pub use self::Vtable::*; | |
16 | pub use self::ObligationCauseCode::*; | |
17 | ||
e9174d1e | 18 | use middle::def_id::DefId; |
bd371182 | 19 | use middle::free_region::FreeRegionMap; |
1a4d82fc | 20 | use middle::subst; |
9cc50fc6 | 21 | use middle::ty::{self, Ty, TypeFoldable}; |
c34b1796 | 22 | use middle::infer::{self, fixup_err_to_string, InferCtxt}; |
e9174d1e | 23 | |
1a4d82fc JJ |
24 | use std::rc::Rc; |
25 | use syntax::ast; | |
26 | use syntax::codemap::{Span, DUMMY_SP}; | |
1a4d82fc | 27 | |
e9174d1e | 28 | pub use self::error_reporting::TraitErrorKey; |
7453a54e | 29 | pub use self::error_reporting::recursive_type_with_infinite_size_error; |
1a4d82fc | 30 | pub use self::error_reporting::report_fulfillment_errors; |
c34b1796 | 31 | pub use self::error_reporting::report_overflow_error; |
7453a54e | 32 | pub use self::error_reporting::report_overflow_error_cycle; |
d9579d0f | 33 | pub use self::error_reporting::report_selection_error; |
e9174d1e | 34 | pub use self::error_reporting::report_object_safety_error; |
1a4d82fc | 35 | pub use self::coherence::orphan_check; |
85aaf69f | 36 | pub use self::coherence::overlapping_impls; |
1a4d82fc | 37 | pub use self::coherence::OrphanCheckErr; |
7453a54e | 38 | pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation}; |
1a4d82fc JJ |
39 | pub use self::project::MismatchedProjectionTypes; |
40 | pub use self::project::normalize; | |
41 | pub use self::project::Normalized; | |
42 | pub use self::object_safety::is_object_safe; | |
b039eaaf | 43 | pub use self::object_safety::astconv_object_safety_violations; |
1a4d82fc JJ |
44 | pub use self::object_safety::object_safety_violations; |
45 | pub use self::object_safety::ObjectSafetyViolation; | |
46 | pub use self::object_safety::MethodViolationCode; | |
c34b1796 | 47 | pub use self::object_safety::is_vtable_safe_method; |
92a42be0 | 48 | pub use self::select::EvaluationCache; |
1a4d82fc JJ |
49 | pub use self::select::SelectionContext; |
50 | pub use self::select::SelectionCache; | |
51 | pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; | |
52 | pub use self::select::{MethodMatchedData}; // intentionally don't export variants | |
53 | pub use self::util::elaborate_predicates; | |
54 | pub use self::util::get_vtable_index_of_object_method; | |
55 | pub use self::util::trait_ref_for_builtin_bound; | |
d9579d0f | 56 | pub use self::util::predicate_for_trait_def; |
1a4d82fc JJ |
57 | pub use self::util::supertraits; |
58 | pub use self::util::Supertraits; | |
c34b1796 AL |
59 | pub use self::util::supertrait_def_ids; |
60 | pub use self::util::SupertraitDefIds; | |
1a4d82fc JJ |
61 | pub use self::util::transitive_bounds; |
62 | pub use self::util::upcast; | |
63 | ||
64 | mod coherence; | |
65 | mod error_reporting; | |
66 | mod fulfill; | |
67 | mod project; | |
68 | mod object_safety; | |
69 | mod select; | |
e9174d1e | 70 | mod structural_impls; |
1a4d82fc JJ |
71 | mod util; |
72 | ||
73 | /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for | |
74 | /// which the vtable must be found. The process of finding a vtable is | |
75 | /// called "resolving" the `Obligation`. This process consists of | |
76 | /// either identifying an `impl` (e.g., `impl Eq for int`) that | |
77 | /// provides the required vtable, or else finding a bound that is in | |
78 | /// scope. The eventual result is usually a `Selection` (defined below). | |
85aaf69f | 79 | #[derive(Clone, PartialEq, Eq)] |
1a4d82fc JJ |
80 | pub struct Obligation<'tcx, T> { |
81 | pub cause: ObligationCause<'tcx>, | |
c34b1796 | 82 | pub recursion_depth: usize, |
1a4d82fc JJ |
83 | pub predicate: T, |
84 | } | |
85 | ||
86 | pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; | |
87 | pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; | |
88 | ||
89 | /// Why did we incur this obligation? Used for error reporting. | |
e9174d1e | 90 | #[derive(Clone, Debug, PartialEq, Eq)] |
1a4d82fc JJ |
91 | pub struct ObligationCause<'tcx> { |
92 | pub span: Span, | |
93 | ||
94 | // The id of the fn body that triggered this obligation. This is | |
95 | // used for region obligations to determine the precise | |
96 | // environment in which the region obligation should be evaluated | |
97 | // (in particular, closures can add new assumptions). See the | |
98 | // field `region_obligations` of the `FulfillmentContext` for more | |
99 | // information. | |
100 | pub body_id: ast::NodeId, | |
101 | ||
102 | pub code: ObligationCauseCode<'tcx> | |
103 | } | |
104 | ||
e9174d1e | 105 | #[derive(Clone, Debug, PartialEq, Eq)] |
1a4d82fc JJ |
106 | pub enum ObligationCauseCode<'tcx> { |
107 | /// Not well classified or should be obvious from span. | |
108 | MiscObligation, | |
109 | ||
e9174d1e SL |
110 | /// This is the trait reference from the given projection |
111 | SliceOrArrayElem, | |
112 | ||
113 | /// This is the trait reference from the given projection | |
114 | ProjectionWf(ty::ProjectionTy<'tcx>), | |
115 | ||
1a4d82fc JJ |
116 | /// In an impl of trait X for type Y, type Y must |
117 | /// also implement all supertraits of X. | |
e9174d1e SL |
118 | ItemObligation(DefId), |
119 | ||
120 | /// A type like `&'a T` is WF only if `T: 'a`. | |
121 | ReferenceOutlivesReferent(Ty<'tcx>), | |
1a4d82fc JJ |
122 | |
123 | /// Obligation incurred due to an object cast. | |
124 | ObjectCastObligation(/* Object type */ Ty<'tcx>), | |
125 | ||
126 | /// Various cases where expressions must be sized/copy/etc: | |
127 | AssignmentLhsSized, // L = X implies that L is Sized | |
128 | StructInitializerSized, // S { ... } must be Sized | |
129 | VariableType(ast::NodeId), // Type of each variable must be Sized | |
130 | ReturnType, // Return type must be Sized | |
131 | RepeatVec, // [T,..n] --> T must be Copy | |
132 | ||
133 | // Captures of variable the given id by a closure (span is the | |
134 | // span of the closure) | |
135 | ClosureCapture(ast::NodeId, Span, ty::BuiltinBound), | |
136 | ||
137 | // Types of fields (other than the last) in a struct must be sized. | |
138 | FieldSized, | |
139 | ||
1a4d82fc JJ |
140 | // static items must have `Sync` type |
141 | SharedStatic, | |
142 | ||
143 | BuiltinDerivedObligation(DerivedObligationCause<'tcx>), | |
144 | ||
145 | ImplDerivedObligation(DerivedObligationCause<'tcx>), | |
85aaf69f SL |
146 | |
147 | CompareImplMethodObligation, | |
1a4d82fc JJ |
148 | } |
149 | ||
e9174d1e | 150 | #[derive(Clone, Debug, PartialEq, Eq)] |
1a4d82fc JJ |
151 | pub struct DerivedObligationCause<'tcx> { |
152 | /// The trait reference of the parent obligation that led to the | |
153 | /// current obligation. Note that only trait obligations lead to | |
154 | /// derived obligations, so we just store the trait reference here | |
155 | /// directly. | |
156 | parent_trait_ref: ty::PolyTraitRef<'tcx>, | |
157 | ||
158 | /// The parent trait had this cause | |
159 | parent_code: Rc<ObligationCauseCode<'tcx>> | |
160 | } | |
161 | ||
62682a34 SL |
162 | pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>; |
163 | pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>; | |
164 | pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>; | |
1a4d82fc JJ |
165 | |
166 | pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; | |
167 | ||
85aaf69f | 168 | #[derive(Clone,Debug)] |
1a4d82fc JJ |
169 | pub enum SelectionError<'tcx> { |
170 | Unimplemented, | |
1a4d82fc JJ |
171 | OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>, |
172 | ty::PolyTraitRef<'tcx>, | |
e9174d1e SL |
173 | ty::error::TypeError<'tcx>), |
174 | TraitNotObjectSafe(DefId), | |
1a4d82fc JJ |
175 | } |
176 | ||
177 | pub struct FulfillmentError<'tcx> { | |
178 | pub obligation: PredicateObligation<'tcx>, | |
179 | pub code: FulfillmentErrorCode<'tcx> | |
180 | } | |
181 | ||
182 | #[derive(Clone)] | |
183 | pub enum FulfillmentErrorCode<'tcx> { | |
184 | CodeSelectionError(SelectionError<'tcx>), | |
185 | CodeProjectionError(MismatchedProjectionTypes<'tcx>), | |
186 | CodeAmbiguity, | |
187 | } | |
188 | ||
189 | /// When performing resolution, it is typically the case that there | |
190 | /// can be one of three outcomes: | |
191 | /// | |
192 | /// - `Ok(Some(r))`: success occurred with result `r` | |
193 | /// - `Ok(None)`: could not definitely determine anything, usually due | |
194 | /// to inconclusive type inference. | |
195 | /// - `Err(e)`: error `e` occurred | |
196 | pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>; | |
197 | ||
198 | /// Given the successful resolution of an obligation, the `Vtable` | |
199 | /// indicates where the vtable comes from. Note that while we call this | |
200 | /// a "vtable", it does not necessarily indicate dynamic dispatch at | |
201 | /// runtime. `Vtable` instances just tell the compiler where to find | |
202 | /// methods, but in generic code those methods are typically statically | |
203 | /// dispatched -- only when an object is constructed is a `Vtable` | |
204 | /// instance reified into an actual vtable. | |
205 | /// | |
206 | /// For example, the vtable may be tied to a specific impl (case A), | |
207 | /// or it may be relative to some bound that is in scope (case B). | |
208 | /// | |
209 | /// | |
210 | /// ``` | |
211 | /// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1 | |
212 | /// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2 | |
213 | /// impl Clone for int { ... } // Impl_3 | |
214 | /// | |
215 | /// fn foo<T:Clone>(concrete: Option<Box<int>>, | |
216 | /// param: T, | |
217 | /// mixed: Option<T>) { | |
218 | /// | |
219 | /// // Case A: Vtable points at a specific impl. Only possible when | |
220 | /// // type is concretely known. If the impl itself has bounded | |
221 | /// // type parameters, Vtable will carry resolutions for those as well: | |
222 | /// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])]) | |
223 | /// | |
224 | /// // Case B: Vtable must be provided by caller. This applies when | |
225 | /// // type is a type parameter. | |
226 | /// param.clone(); // VtableParam | |
227 | /// | |
228 | /// // Case C: A mix of cases A and B. | |
229 | /// mixed.clone(); // Vtable(Impl_1, [VtableParam]) | |
230 | /// } | |
231 | /// ``` | |
232 | /// | |
233 | /// ### The type parameter `N` | |
234 | /// | |
235 | /// See explanation on `VtableImplData`. | |
62682a34 | 236 | #[derive(Clone)] |
1a4d82fc JJ |
237 | pub enum Vtable<'tcx, N> { |
238 | /// Vtable identifying a particular impl. | |
239 | VtableImpl(VtableImplData<'tcx, N>), | |
240 | ||
c34b1796 AL |
241 | /// Vtable for default trait implementations |
242 | /// This carries the information and nested obligations with regards | |
243 | /// to a default implementation for a trait `Trait`. The nested obligations | |
244 | /// ensure the trait implementation holds for all the constituent types. | |
245 | VtableDefaultImpl(VtableDefaultImplData<N>), | |
246 | ||
1a4d82fc | 247 | /// Successful resolution to an obligation provided by the caller |
85aaf69f SL |
248 | /// for some type parameter. The `Vec<N>` represents the |
249 | /// obligations incurred from normalizing the where-clause (if | |
250 | /// any). | |
251 | VtableParam(Vec<N>), | |
1a4d82fc JJ |
252 | |
253 | /// Virtual calls through an object | |
254 | VtableObject(VtableObjectData<'tcx>), | |
255 | ||
256 | /// Successful resolution for a builtin trait. | |
257 | VtableBuiltin(VtableBuiltinData<N>), | |
258 | ||
85aaf69f SL |
259 | /// Vtable automatically generated for a closure. The def ID is the ID |
260 | /// of the closure expression. This is a `VtableImpl` in spirit, but the | |
261 | /// impl is generated by the compiler and does not appear in the source. | |
62682a34 | 262 | VtableClosure(VtableClosureData<'tcx, N>), |
1a4d82fc JJ |
263 | |
264 | /// Same as above, but for a fn pointer type with the given signature. | |
265 | VtableFnPointer(ty::Ty<'tcx>), | |
266 | } | |
267 | ||
268 | /// Identifies a particular impl in the source, along with a set of | |
269 | /// substitutions from the impl's type/lifetime parameters. The | |
270 | /// `nested` vector corresponds to the nested obligations attached to | |
271 | /// the impl's type parameters. | |
272 | /// | |
273 | /// The type parameter `N` indicates the type used for "nested | |
274 | /// obligations" that are required by the impl. During type check, this | |
275 | /// is `Obligation`, as one might expect. During trans, however, this | |
276 | /// is `()`, because trans only requires a shallow resolution of an | |
277 | /// impl, and nested obligations are satisfied later. | |
85aaf69f | 278 | #[derive(Clone, PartialEq, Eq)] |
1a4d82fc | 279 | pub struct VtableImplData<'tcx, N> { |
e9174d1e | 280 | pub impl_def_id: DefId, |
1a4d82fc | 281 | pub substs: subst::Substs<'tcx>, |
62682a34 SL |
282 | pub nested: Vec<N> |
283 | } | |
284 | ||
285 | #[derive(Clone, PartialEq, Eq)] | |
286 | pub struct VtableClosureData<'tcx, N> { | |
e9174d1e | 287 | pub closure_def_id: DefId, |
c1a9b12d | 288 | pub substs: ty::ClosureSubsts<'tcx>, |
62682a34 SL |
289 | /// Nested obligations. This can be non-empty if the closure |
290 | /// signature contains associated types. | |
291 | pub nested: Vec<N> | |
1a4d82fc JJ |
292 | } |
293 | ||
62682a34 | 294 | #[derive(Clone)] |
c34b1796 | 295 | pub struct VtableDefaultImplData<N> { |
e9174d1e | 296 | pub trait_def_id: DefId, |
c34b1796 AL |
297 | pub nested: Vec<N> |
298 | } | |
299 | ||
62682a34 | 300 | #[derive(Clone)] |
1a4d82fc | 301 | pub struct VtableBuiltinData<N> { |
62682a34 | 302 | pub nested: Vec<N> |
1a4d82fc JJ |
303 | } |
304 | ||
305 | /// A vtable for some object-safe trait `Foo` automatically derived | |
306 | /// for the object type `Foo`. | |
307 | #[derive(PartialEq,Eq,Clone)] | |
308 | pub struct VtableObjectData<'tcx> { | |
c34b1796 AL |
309 | /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. |
310 | pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, | |
c1a9b12d SL |
311 | |
312 | /// The vtable is formed by concatenating together the method lists of | |
313 | /// the base object trait and all supertraits; this is the start of | |
314 | /// `upcast_trait_ref`'s methods in that vtable. | |
315 | pub vtable_base: usize | |
1a4d82fc JJ |
316 | } |
317 | ||
1a4d82fc | 318 | /// Creates predicate obligations from the generic bounds. |
62682a34 | 319 | pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, |
85aaf69f | 320 | generic_bounds: &ty::InstantiatedPredicates<'tcx>) |
1a4d82fc JJ |
321 | -> PredicateObligations<'tcx> |
322 | { | |
62682a34 | 323 | util::predicates_for_generics(cause, 0, generic_bounds) |
1a4d82fc JJ |
324 | } |
325 | ||
326 | /// Determines whether the type `ty` is known to meet `bound` and | |
327 | /// returns true if so. Returns false if `ty` either does not meet | |
328 | /// `bound` or is not known to meet bound (note that this is | |
329 | /// conservative towards *no impl*, which is the opposite of the | |
330 | /// `evaluate` methods). | |
62682a34 | 331 | pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, |
62682a34 SL |
332 | ty: Ty<'tcx>, |
333 | bound: ty::BuiltinBound, | |
334 | span: Span) | |
335 | -> bool | |
1a4d82fc | 336 | { |
62682a34 SL |
337 | debug!("type_known_to_meet_builtin_bound(ty={:?}, bound={:?})", |
338 | ty, | |
1a4d82fc JJ |
339 | bound); |
340 | ||
1a4d82fc | 341 | let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); |
92a42be0 SL |
342 | let obligation = |
343 | util::predicate_for_builtin_bound(infcx.tcx, cause, bound, 0, ty); | |
344 | let obligation = match obligation { | |
345 | Ok(o) => o, | |
346 | Err(..) => return false | |
347 | }; | |
348 | let result = SelectionContext::new(infcx) | |
349 | .evaluate_obligation_conservatively(&obligation); | |
350 | debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}", | |
351 | ty, bound, result); | |
352 | ||
353 | if result && (ty.has_infer_types() || ty.has_closure_types()) { | |
354 | // Because of inference "guessing", selection can sometimes claim | |
355 | // to succeed while the success requires a guess. To ensure | |
356 | // this function's result remains infallible, we must confirm | |
357 | // that guess. While imperfect, I believe this is sound. | |
358 | ||
7453a54e | 359 | let mut fulfill_cx = FulfillmentContext::new(); |
92a42be0 SL |
360 | |
361 | // We can use a dummy node-id here because we won't pay any mind | |
362 | // to region obligations that arise (there shouldn't really be any | |
363 | // anyhow). | |
364 | let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); | |
365 | ||
366 | fulfill_cx.register_builtin_bound(infcx, ty, bound, cause); | |
367 | ||
368 | // Note: we only assume something is `Copy` if we can | |
369 | // *definitively* show that it implements `Copy`. Otherwise, | |
370 | // assume it is move; linear is always ok. | |
371 | match fulfill_cx.select_all_or_error(infcx) { | |
372 | Ok(()) => { | |
373 | debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success", | |
374 | ty, | |
375 | bound); | |
376 | true | |
377 | } | |
378 | Err(e) => { | |
379 | debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}", | |
380 | ty, | |
381 | bound, | |
382 | e); | |
383 | false | |
384 | } | |
1a4d82fc | 385 | } |
92a42be0 SL |
386 | } else { |
387 | result | |
1a4d82fc JJ |
388 | } |
389 | } | |
390 | ||
c1a9b12d | 391 | // FIXME: this is gonna need to be removed ... |
c34b1796 | 392 | /// Normalizes the parameter environment, reporting errors if they occur. |
85aaf69f SL |
393 | pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>, |
394 | cause: ObligationCause<'tcx>) | |
395 | -> ty::ParameterEnvironment<'a,'tcx> | |
396 | { | |
c34b1796 AL |
397 | // I'm not wild about reporting errors here; I'd prefer to |
398 | // have the errors get reported at a defined place (e.g., | |
399 | // during typeck). Instead I have all parameter | |
400 | // environments, in effect, going through this function | |
401 | // and hence potentially reporting errors. This ensurse of | |
402 | // course that we never forget to normalize (the | |
403 | // alternative seemed like it would involve a lot of | |
404 | // manual invocations of this fn -- and then we'd have to | |
405 | // deal with the errors at each of those sites). | |
406 | // | |
407 | // In any case, in practice, typeck constructs all the | |
408 | // parameter environments once for every fn as it goes, | |
409 | // and errors will get reported then; so after typeck we | |
410 | // can be sure that no errors should occur. | |
411 | ||
412 | let tcx = unnormalized_env.tcx; | |
413 | let span = cause.span; | |
414 | let body_id = cause.body_id; | |
415 | ||
62682a34 SL |
416 | debug!("normalize_param_env_or_error(unnormalized_env={:?})", |
417 | unnormalized_env); | |
418 | ||
419 | let predicates: Vec<_> = | |
420 | util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.clone()) | |
421 | .filter(|p| !p.is_global()) // (*) | |
422 | .collect(); | |
423 | ||
424 | // (*) Any predicate like `i32: Trait<u32>` or whatever doesn't | |
425 | // need to be in the *environment* to be proven, so screen those | |
426 | // out. This is important for the soundness of inter-fn | |
427 | // caching. Note though that we should probably check that these | |
428 | // predicates hold at the point where the environment is | |
429 | // constructed, but I am not currently doing so out of laziness. | |
430 | // -nmatsakis | |
431 | ||
432 | debug!("normalize_param_env_or_error: elaborated-predicates={:?}", | |
433 | predicates); | |
434 | ||
435 | let elaborated_env = unnormalized_env.with_caller_bounds(predicates); | |
c34b1796 | 436 | |
7453a54e SL |
437 | let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env)); |
438 | let predicates = match fully_normalize(&infcx, | |
439 | cause, | |
c1a9b12d | 440 | &infcx.parameter_environment.caller_bounds) { |
c34b1796 | 441 | Ok(predicates) => predicates, |
85aaf69f | 442 | Err(errors) => { |
85aaf69f | 443 | report_fulfillment_errors(&infcx, &errors); |
c1a9b12d | 444 | return infcx.parameter_environment; // an unnormalized env is better than nothing |
85aaf69f | 445 | } |
c34b1796 | 446 | }; |
85aaf69f | 447 | |
7453a54e SL |
448 | debug!("normalize_param_env_or_error: normalized predicates={:?}", |
449 | predicates); | |
450 | ||
bd371182 AL |
451 | let free_regions = FreeRegionMap::new(); |
452 | infcx.resolve_regions_and_report_errors(&free_regions, body_id); | |
c34b1796 AL |
453 | let predicates = match infcx.fully_resolve(&predicates) { |
454 | Ok(predicates) => predicates, | |
455 | Err(fixup_err) => { | |
456 | // If we encounter a fixup error, it means that some type | |
457 | // variable wound up unconstrained. I actually don't know | |
458 | // if this can happen, and I certainly don't expect it to | |
459 | // happen often, but if it did happen it probably | |
460 | // represents a legitimate failure due to some kind of | |
461 | // unconstrained variable, and it seems better not to ICE, | |
462 | // all things considered. | |
463 | let err_msg = fixup_err_to_string(fixup_err); | |
464 | tcx.sess.span_err(span, &err_msg); | |
c1a9b12d | 465 | return infcx.parameter_environment; // an unnormalized env is better than nothing |
c34b1796 AL |
466 | } |
467 | }; | |
85aaf69f | 468 | |
7453a54e SL |
469 | debug!("normalize_param_env_or_error: resolved predicates={:?}", |
470 | predicates); | |
471 | ||
c1a9b12d | 472 | infcx.parameter_environment.with_caller_bounds(predicates) |
85aaf69f SL |
473 | } |
474 | ||
475 | pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, | |
85aaf69f SL |
476 | cause: ObligationCause<'tcx>, |
477 | value: &T) | |
478 | -> Result<T, Vec<FulfillmentError<'tcx>>> | |
9cc50fc6 | 479 | where T : TypeFoldable<'tcx> |
85aaf69f | 480 | { |
7453a54e | 481 | debug!("fully_normalize(value={:?})", value); |
85aaf69f | 482 | |
c1a9b12d SL |
483 | let mut selcx = &mut SelectionContext::new(infcx); |
484 | // FIXME (@jroesch) ISSUE 26721 | |
485 | // I'm not sure if this is a bug or not, needs further investigation. | |
486 | // It appears that by reusing the fulfillment_cx here we incur more | |
487 | // obligations and later trip an asssertion on regionck.rs line 337. | |
488 | // | |
489 | // The two possibilities I see is: | |
490 | // - normalization is not actually fully happening and we | |
491 | // have a bug else where | |
492 | // - we are adding a duplicate bound into the list causing | |
493 | // its size to change. | |
494 | // | |
495 | // I think we should probably land this refactor and then come | |
496 | // back to this is a follow-up patch. | |
7453a54e | 497 | let mut fulfill_cx = FulfillmentContext::new(); |
c1a9b12d | 498 | |
85aaf69f SL |
499 | let Normalized { value: normalized_value, obligations } = |
500 | project::normalize(selcx, cause, value); | |
7453a54e | 501 | debug!("fully_normalize: normalized_value={:?} obligations={:?}", |
62682a34 SL |
502 | normalized_value, |
503 | obligations); | |
85aaf69f SL |
504 | for obligation in obligations { |
505 | fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation); | |
506 | } | |
c1a9b12d | 507 | |
7453a54e SL |
508 | debug!("fully_normalize: select_all_or_error start"); |
509 | match fulfill_cx.select_all_or_error(infcx) { | |
510 | Ok(()) => { } | |
511 | Err(e) => { | |
512 | debug!("fully_normalize: error={:?}", e); | |
513 | return Err(e); | |
514 | } | |
515 | } | |
516 | debug!("fully_normalize: select_all_or_error complete"); | |
85aaf69f | 517 | let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value); |
7453a54e | 518 | debug!("fully_normalize: resolved_value={:?}", resolved_value); |
85aaf69f SL |
519 | Ok(resolved_value) |
520 | } | |
521 | ||
1a4d82fc JJ |
522 | impl<'tcx,O> Obligation<'tcx,O> { |
523 | pub fn new(cause: ObligationCause<'tcx>, | |
524 | trait_ref: O) | |
525 | -> Obligation<'tcx, O> | |
526 | { | |
527 | Obligation { cause: cause, | |
528 | recursion_depth: 0, | |
529 | predicate: trait_ref } | |
530 | } | |
531 | ||
532 | fn with_depth(cause: ObligationCause<'tcx>, | |
c34b1796 | 533 | recursion_depth: usize, |
1a4d82fc JJ |
534 | trait_ref: O) |
535 | -> Obligation<'tcx, O> | |
536 | { | |
537 | Obligation { cause: cause, | |
538 | recursion_depth: recursion_depth, | |
539 | predicate: trait_ref } | |
540 | } | |
541 | ||
542 | pub fn misc(span: Span, body_id: ast::NodeId, trait_ref: O) -> Obligation<'tcx, O> { | |
543 | Obligation::new(ObligationCause::misc(span, body_id), trait_ref) | |
544 | } | |
545 | ||
546 | pub fn with<P>(&self, value: P) -> Obligation<'tcx,P> { | |
547 | Obligation { cause: self.cause.clone(), | |
548 | recursion_depth: self.recursion_depth, | |
549 | predicate: value } | |
550 | } | |
551 | } | |
552 | ||
553 | impl<'tcx> ObligationCause<'tcx> { | |
554 | pub fn new(span: Span, | |
555 | body_id: ast::NodeId, | |
556 | code: ObligationCauseCode<'tcx>) | |
557 | -> ObligationCause<'tcx> { | |
558 | ObligationCause { span: span, body_id: body_id, code: code } | |
559 | } | |
560 | ||
561 | pub fn misc(span: Span, body_id: ast::NodeId) -> ObligationCause<'tcx> { | |
562 | ObligationCause { span: span, body_id: body_id, code: MiscObligation } | |
563 | } | |
564 | ||
565 | pub fn dummy() -> ObligationCause<'tcx> { | |
566 | ObligationCause { span: DUMMY_SP, body_id: 0, code: MiscObligation } | |
567 | } | |
568 | } | |
569 | ||
570 | impl<'tcx, N> Vtable<'tcx, N> { | |
62682a34 | 571 | pub fn nested_obligations(self) -> Vec<N> { |
1a4d82fc | 572 | match self { |
62682a34 SL |
573 | VtableImpl(i) => i.nested, |
574 | VtableParam(n) => n, | |
575 | VtableBuiltin(i) => i.nested, | |
576 | VtableDefaultImpl(d) => d.nested, | |
577 | VtableClosure(c) => c.nested, | |
578 | VtableObject(_) | VtableFnPointer(..) => vec![] | |
c34b1796 AL |
579 | } |
580 | } | |
581 | ||
62682a34 SL |
582 | pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M { |
583 | match self { | |
584 | VtableImpl(i) => VtableImpl(VtableImplData { | |
585 | impl_def_id: i.impl_def_id, | |
586 | substs: i.substs, | |
587 | nested: i.nested.into_iter().map(f).collect() | |
588 | }), | |
589 | VtableParam(n) => VtableParam(n.into_iter().map(f).collect()), | |
590 | VtableBuiltin(i) => VtableBuiltin(VtableBuiltinData { | |
591 | nested: i.nested.into_iter().map(f).collect() | |
592 | }), | |
593 | VtableObject(o) => VtableObject(o), | |
594 | VtableDefaultImpl(d) => VtableDefaultImpl(VtableDefaultImplData { | |
595 | trait_def_id: d.trait_def_id, | |
596 | nested: d.nested.into_iter().map(f).collect() | |
597 | }), | |
598 | VtableFnPointer(f) => VtableFnPointer(f), | |
599 | VtableClosure(c) => VtableClosure(VtableClosureData { | |
600 | closure_def_id: c.closure_def_id, | |
601 | substs: c.substs, | |
c1a9b12d | 602 | nested: c.nested.into_iter().map(f).collect(), |
62682a34 | 603 | }) |
1a4d82fc JJ |
604 | } |
605 | } | |
606 | } | |
607 | ||
608 | impl<'tcx> FulfillmentError<'tcx> { | |
609 | fn new(obligation: PredicateObligation<'tcx>, | |
610 | code: FulfillmentErrorCode<'tcx>) | |
611 | -> FulfillmentError<'tcx> | |
612 | { | |
613 | FulfillmentError { obligation: obligation, code: code } | |
614 | } | |
1a4d82fc JJ |
615 | } |
616 | ||
617 | impl<'tcx> TraitObligation<'tcx> { | |
c34b1796 AL |
618 | fn self_ty(&self) -> ty::Binder<Ty<'tcx>> { |
619 | ty::Binder(self.predicate.skip_binder().self_ty()) | |
1a4d82fc JJ |
620 | } |
621 | } |