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