]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/outlives/obligations.rs
Use assert_eq! in copy_from_slice
[rust.git] / src / librustc / infer / outlives / obligations.rs
1 // Copyright 2012-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
11 //! Code that handles "type-outlives" constraints like `T: 'a`. This
12 //! is based on the `outlives_components` function defined on the tcx,
13 //! but it adds a bit of heuristics on top, in particular to deal with
14 //! associated types and projections.
15 //!
16 //! When we process a given `T: 'a` obligation, we may produce two
17 //! kinds of constraints for the region inferencer:
18 //!
19 //! - Relationships between inference variables and other regions.
20 //!   For example, if we have `&'?0 u32: 'a`, then we would produce
21 //!   a constraint that `'a <= '?0`.
22 //! - "Verifys" that must be checked after inferencing is done.
23 //!   For example, if we know that, for some type parameter `T`,
24 //!   `T: 'a + 'b`, and we have a requirement that `T: '?1`,
25 //!   then we add a "verify" that checks that `'?1 <= 'a || '?1 <= 'b`.
26 //!   - Note the difference with the previous case: here, the region
27 //!     variable must be less than something else, so this doesn't
28 //!     affect how inference works (it finds the smallest region that
29 //!     will do); it's just a post-condition that we have to check.
30 //!
31 //! **The key point is that once this function is done, we have
32 //! reduced all of our "type-region outlives" obligations into relationships
33 //! between individual regions.**
34 //!
35 //! One key input to this function is the set of "region-bound pairs".
36 //! These are basically the relationships between type parameters and
37 //! regions that are in scope at the point where the outlives
38 //! obligation was incurred. **When type-checking a function,
39 //! particularly in the face of closures, this is not known until
40 //! regionck runs!** This is because some of those bounds come
41 //! from things we have yet to infer.
42 //!
43 //! Consider:
44 //!
45 //! ```
46 //! fn bar<T>(a: T, b: impl for<'a> Fn(&'a T));
47 //! fn foo<T>(x: T) {
48 //!     bar(x, |y| { ... })
49 //!          // ^ closure arg
50 //! }
51 //! ```
52 //!
53 //! Here, the type of `y` may involve inference variables and the
54 //! like, and it may also contain implied bounds that are needed to
55 //! type-check the closure body (e.g., here it informs us that `T`
56 //! outlives the late-bound region `'a`).
57 //!
58 //! Note that by delaying the gathering of implied bounds until all
59 //! inference information is known, we may find relationships between
60 //! bound regions and other regions in the environment. For example,
61 //! when we first check a closure like the one expected as argument
62 //! to `foo`:
63 //!
64 //! ```
65 //! fn foo<U, F: for<'a> FnMut(&'a U)>(_f: F) {}
66 //! ```
67 //!
68 //! the type of the closure's first argument would be `&'a ?U`.  We
69 //! might later infer `?U` to something like `&'b u32`, which would
70 //! imply that `'b: 'a`.
71
72 use hir::def_id::DefId;
73 use infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
74 use traits;
75 use ty::{self, Ty, TyCtxt, TypeFoldable};
76 use ty::subst::{Subst, Substs};
77 use ty::outlives::Component;
78 use syntax::ast;
79
80 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
81     /// Registers that the given region obligation must be resolved
82     /// from within the scope of `body_id`. These regions are enqueued
83     /// and later processed by regionck, when full type information is
84     /// available (see `region_obligations` field for more
85     /// information).
86     pub fn register_region_obligation(
87         &self,
88         body_id: ast::NodeId,
89         obligation: RegionObligation<'tcx>,
90     ) {
91         debug!(
92             "register_region_obligation(body_id={:?}, obligation={:?})",
93             body_id,
94             obligation
95         );
96
97         self.region_obligations
98             .borrow_mut()
99             .push((body_id, obligation));
100     }
101
102     /// Trait queries just want to pass back type obligations "as is"
103     pub fn take_registered_region_obligations(
104         &self,
105     ) -> Vec<(ast::NodeId, RegionObligation<'tcx>)> {
106         ::std::mem::replace(
107             &mut *self.region_obligations.borrow_mut(),
108             vec![],
109         )
110     }
111
112     /// Process the region obligations that must be proven (during
113     /// `regionck`) for the given `body_id`, given information about
114     /// the region bounds in scope and so forth. This function must be
115     /// invoked for all relevant body-ids before region inference is
116     /// done (or else an assert will fire).
117     ///
118     /// See the `region_obligations` field of `InferCtxt` for some
119     /// comments about how this function fits into the overall expected
120     /// flow of the the inferencer. The key point is that it is
121     /// invoked after all type-inference variables have been bound --
122     /// towards the end of regionck. This also ensures that the
123     /// region-bound-pairs are available (see comments above regarding
124     /// closures).
125     ///
126     /// # Parameters
127     ///
128     /// - `region_bound_pairs`: the set of region bounds implied by
129     ///   the parameters and where-clauses. In particular, each pair
130     ///   `('a, K)` in this list tells us that the bounds in scope
131     ///   indicate that `K: 'a`, where `K` is either a generic
132     ///   parameter like `T` or a projection like `T::Item`.
133     /// - `implicit_region_bound`: if some, this is a region bound
134     ///   that is considered to hold for all type parameters (the
135     ///   function body).
136     /// - `param_env` is the parameter environment for the enclosing function.
137     /// - `body_id` is the body-id whose region obligations are being
138     ///   processed.
139     ///
140     /// # Returns
141     ///
142     /// This function may have to perform normalizations, and hence it
143     /// returns an `InferOk` with subobligations that must be
144     /// processed.
145     pub fn process_registered_region_obligations(
146         &self,
147         region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
148         implicit_region_bound: Option<ty::Region<'tcx>>,
149         param_env: ty::ParamEnv<'tcx>,
150         body_id: ast::NodeId,
151     ) {
152         assert!(
153             !self.in_snapshot.get(),
154             "cannot process registered region obligations in a snapshot"
155         );
156
157         debug!("process_registered_region_obligations()");
158
159         // pull out the region obligations with the given `body_id` (leaving the rest)
160         let mut my_region_obligations = Vec::with_capacity(self.region_obligations.borrow().len());
161         {
162             let mut r_o = self.region_obligations.borrow_mut();
163             for (_, obligation) in r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id) {
164                 my_region_obligations.push(obligation);
165             }
166         }
167
168         let outlives =
169             TypeOutlives::new(self, region_bound_pairs, implicit_region_bound, param_env);
170
171         for RegionObligation {
172             sup_type,
173             sub_region,
174             cause,
175         } in my_region_obligations
176         {
177             debug!(
178                 "process_registered_region_obligations: sup_type={:?} sub_region={:?} cause={:?}",
179                 sup_type,
180                 sub_region,
181                 cause
182             );
183
184             let origin = SubregionOrigin::from_obligation_cause(
185                 &cause,
186                 || infer::RelateParamBound(cause.span, sup_type),
187             );
188
189             outlives.type_must_outlive(origin, sup_type, sub_region);
190         }
191     }
192
193     /// Processes a single ad-hoc region obligation that was not
194     /// registered in advance.
195     pub fn type_must_outlive(
196         &self,
197         region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
198         implicit_region_bound: Option<ty::Region<'tcx>>,
199         param_env: ty::ParamEnv<'tcx>,
200         origin: infer::SubregionOrigin<'tcx>,
201         ty: Ty<'tcx>,
202         region: ty::Region<'tcx>,
203     ) {
204         let outlives =
205             TypeOutlives::new(self, region_bound_pairs, implicit_region_bound, param_env);
206         outlives.type_must_outlive(origin, ty, region);
207     }
208 }
209
210 #[must_use] // you ought to invoke `into_accrued_obligations` when you are done =)
211 struct TypeOutlives<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
212     // See the comments on `process_registered_region_obligations` for the meaning
213     // of these fields.
214     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
215     region_bound_pairs: &'cx [(ty::Region<'tcx>, GenericKind<'tcx>)],
216     implicit_region_bound: Option<ty::Region<'tcx>>,
217     param_env: ty::ParamEnv<'tcx>,
218 }
219
220 impl<'cx, 'gcx, 'tcx> TypeOutlives<'cx, 'gcx, 'tcx> {
221     fn new(
222         infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
223         region_bound_pairs: &'cx [(ty::Region<'tcx>, GenericKind<'tcx>)],
224         implicit_region_bound: Option<ty::Region<'tcx>>,
225         param_env: ty::ParamEnv<'tcx>,
226     ) -> Self {
227         Self {
228             infcx,
229             region_bound_pairs,
230             implicit_region_bound,
231             param_env,
232         }
233     }
234
235     /// Adds constraints to inference such that `T: 'a` holds (or
236     /// reports an error if it cannot).
237     ///
238     /// # Parameters
239     ///
240     /// - `origin`, the reason we need this constraint
241     /// - `ty`, the type `T`
242     /// - `region`, the region `'a`
243     fn type_must_outlive(
244         &self,
245         origin: infer::SubregionOrigin<'tcx>,
246         ty: Ty<'tcx>,
247         region: ty::Region<'tcx>,
248     ) {
249         let ty = self.infcx.resolve_type_vars_if_possible(&ty);
250
251         debug!(
252             "type_must_outlive(ty={:?}, region={:?}, origin={:?})",
253             ty,
254             region,
255             origin
256         );
257
258         assert!(!ty.has_escaping_regions());
259
260         let components = self.tcx().outlives_components(ty);
261         self.components_must_outlive(origin, components, region);
262     }
263
264     fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
265         self.infcx.tcx
266     }
267
268     fn components_must_outlive(
269         &self,
270         origin: infer::SubregionOrigin<'tcx>,
271         components: Vec<Component<'tcx>>,
272         region: ty::Region<'tcx>,
273     ) {
274         for component in components {
275             let origin = origin.clone();
276             match component {
277                 Component::Region(region1) => {
278                     self.infcx.sub_regions(origin, region, region1);
279                 }
280                 Component::Param(param_ty) => {
281                     self.param_ty_must_outlive(origin, region, param_ty);
282                 }
283                 Component::Projection(projection_ty) => {
284                     self.projection_must_outlive(origin, region, projection_ty);
285                 }
286                 Component::EscapingProjection(subcomponents) => {
287                     self.components_must_outlive(origin, subcomponents, region);
288                 }
289                 Component::UnresolvedInferenceVariable(v) => {
290                     // ignore this, we presume it will yield an error
291                     // later, since if a type variable is not resolved by
292                     // this point it never will be
293                     self.infcx.tcx.sess.delay_span_bug(
294                         origin.span(),
295                         &format!("unresolved inference variable in outlives: {:?}", v),
296                     );
297                 }
298             }
299         }
300     }
301
302     fn param_ty_must_outlive(
303         &self,
304         origin: infer::SubregionOrigin<'tcx>,
305         region: ty::Region<'tcx>,
306         param_ty: ty::ParamTy,
307     ) {
308         debug!(
309             "param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
310             region,
311             param_ty,
312             origin
313         );
314
315         let verify_bound = self.param_bound(param_ty);
316         let generic = GenericKind::Param(param_ty);
317         self.infcx
318             .verify_generic_bound(origin, generic, region, verify_bound);
319     }
320
321     fn projection_must_outlive(
322         &self,
323         origin: infer::SubregionOrigin<'tcx>,
324         region: ty::Region<'tcx>,
325         projection_ty: ty::ProjectionTy<'tcx>,
326     ) {
327         debug!(
328             "projection_must_outlive(region={:?}, projection_ty={:?}, origin={:?})",
329             region,
330             projection_ty,
331             origin
332         );
333
334         // This case is thorny for inference. The fundamental problem is
335         // that there are many cases where we have choice, and inference
336         // doesn't like choice (the current region inference in
337         // particular). :) First off, we have to choose between using the
338         // OutlivesProjectionEnv, OutlivesProjectionTraitDef, and
339         // OutlivesProjectionComponent rules, any one of which is
340         // sufficient.  If there are no inference variables involved, it's
341         // not hard to pick the right rule, but if there are, we're in a
342         // bit of a catch 22: if we picked which rule we were going to
343         // use, we could add constraints to the region inference graph
344         // that make it apply, but if we don't add those constraints, the
345         // rule might not apply (but another rule might). For now, we err
346         // on the side of adding too few edges into the graph.
347
348         // Compute the bounds we can derive from the environment or trait
349         // definition.  We know that the projection outlives all the
350         // regions in this list.
351         let env_bounds = self.projection_declared_bounds(projection_ty);
352
353         debug!("projection_must_outlive: env_bounds={:?}", env_bounds);
354
355         // If we know that the projection outlives 'static, then we're
356         // done here.
357         if env_bounds.contains(&&ty::ReStatic) {
358             debug!("projection_must_outlive: 'static as declared bound");
359             return;
360         }
361
362         // If declared bounds list is empty, the only applicable rule is
363         // OutlivesProjectionComponent. If there are inference variables,
364         // then, we can break down the outlives into more primitive
365         // components without adding unnecessary edges.
366         //
367         // If there are *no* inference variables, however, we COULD do
368         // this, but we choose not to, because the error messages are less
369         // good. For example, a requirement like `T::Item: 'r` would be
370         // translated to a requirement that `T: 'r`; when this is reported
371         // to the user, it will thus say "T: 'r must hold so that T::Item:
372         // 'r holds". But that makes it sound like the only way to fix
373         // the problem is to add `T: 'r`, which isn't true. So, if there are no
374         // inference variables, we use a verify constraint instead of adding
375         // edges, which winds up enforcing the same condition.
376         let needs_infer = projection_ty.needs_infer();
377         if env_bounds.is_empty() && needs_infer {
378             debug!("projection_must_outlive: no declared bounds");
379
380             for component_ty in projection_ty.substs.types() {
381                 self.type_must_outlive(origin.clone(), component_ty, region);
382             }
383
384             for r in projection_ty.substs.regions() {
385                 self.infcx.sub_regions(origin.clone(), region, r);
386             }
387
388             return;
389         }
390
391         // If we find that there is a unique declared bound `'b`, and this bound
392         // appears in the trait reference, then the best action is to require that `'b:'r`,
393         // so do that. This is best no matter what rule we use:
394         //
395         // - OutlivesProjectionEnv or OutlivesProjectionTraitDef: these would translate to
396         // the requirement that `'b:'r`
397         // - OutlivesProjectionComponent: this would require `'b:'r` in addition to
398         // other conditions
399         if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) {
400             let unique_bound = env_bounds[0];
401             debug!(
402                 "projection_must_outlive: unique declared bound = {:?}",
403                 unique_bound
404             );
405             if projection_ty
406                 .substs
407                 .regions()
408                 .any(|r| env_bounds.contains(&r))
409             {
410                 debug!("projection_must_outlive: unique declared bound appears in trait ref");
411                 self.infcx.sub_regions(origin.clone(), region, unique_bound);
412                 return;
413             }
414         }
415
416         // Fallback to verifying after the fact that there exists a
417         // declared bound, or that all the components appearing in the
418         // projection outlive; in some cases, this may add insufficient
419         // edges into the inference graph, leading to inference failures
420         // even though a satisfactory solution exists.
421         let verify_bound = self.projection_bound(env_bounds, projection_ty);
422         let generic = GenericKind::Projection(projection_ty);
423         self.infcx
424             .verify_generic_bound(origin, generic.clone(), region, verify_bound);
425     }
426
427     fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
428         match ty.sty {
429             ty::TyParam(p) => self.param_bound(p),
430             ty::TyProjection(data) => {
431                 let declared_bounds = self.projection_declared_bounds(data);
432                 self.projection_bound(declared_bounds, data)
433             }
434             _ => self.recursive_type_bound(ty),
435         }
436     }
437
438     fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
439         debug!("param_bound(param_ty={:?})", param_ty);
440
441         let mut param_bounds = self.declared_generic_bounds_from_env(GenericKind::Param(param_ty));
442
443         // Add in the default bound of fn body that applies to all in
444         // scope type parameters:
445         param_bounds.extend(self.implicit_region_bound);
446
447         VerifyBound::AnyRegion(param_bounds)
448     }
449
450     fn projection_declared_bounds(
451         &self,
452         projection_ty: ty::ProjectionTy<'tcx>,
453     ) -> Vec<ty::Region<'tcx>> {
454         // First assemble bounds from where clauses and traits.
455
456         let mut declared_bounds =
457             self.declared_generic_bounds_from_env(GenericKind::Projection(projection_ty));
458
459         declared_bounds
460             .extend_from_slice(&self.declared_projection_bounds_from_trait(projection_ty));
461
462         declared_bounds
463     }
464
465     fn projection_bound(
466         &self,
467         declared_bounds: Vec<ty::Region<'tcx>>,
468         projection_ty: ty::ProjectionTy<'tcx>,
469     ) -> VerifyBound<'tcx> {
470         debug!(
471             "projection_bound(declared_bounds={:?}, projection_ty={:?})",
472             declared_bounds,
473             projection_ty
474         );
475
476         // see the extensive comment in projection_must_outlive
477         let ty = self.infcx
478             .tcx
479             .mk_projection(projection_ty.item_def_id, projection_ty.substs);
480         let recursive_bound = self.recursive_type_bound(ty);
481
482         VerifyBound::AnyRegion(declared_bounds).or(recursive_bound)
483     }
484
485     fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
486         let mut bounds = vec![];
487
488         for subty in ty.walk_shallow() {
489             bounds.push(self.type_bound(subty));
490         }
491
492         let mut regions = ty.regions();
493         regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
494         bounds.push(VerifyBound::AllRegions(regions));
495
496         // remove bounds that must hold, since they are not interesting
497         bounds.retain(|b| !b.must_hold());
498
499         if bounds.len() == 1 {
500             bounds.pop().unwrap()
501         } else {
502             VerifyBound::AllBounds(bounds)
503         }
504     }
505
506     fn declared_generic_bounds_from_env(
507         &self,
508         generic: GenericKind<'tcx>,
509     ) -> Vec<ty::Region<'tcx>> {
510         let tcx = self.tcx();
511
512         // To start, collect bounds from user environment. Note that
513         // parameter environments are already elaborated, so we don't
514         // have to worry about that. Comparing using `==` is a bit
515         // dubious for projections, but it will work for simple cases
516         // like `T` and `T::Item`. It may not work as well for things
517         // like `<T as Foo<'a>>::Item`.
518         let generic_ty = generic.to_ty(tcx);
519         let c_b = self.param_env.caller_bounds;
520         let mut param_bounds = self.collect_outlives_from_predicate_list(generic_ty, c_b);
521
522         // Next, collect regions we scraped from the well-formedness
523         // constraints in the fn signature. To do that, we walk the list
524         // of known relations from the fn ctxt.
525         //
526         // This is crucial because otherwise code like this fails:
527         //
528         //     fn foo<'a, A>(x: &'a A) { x.bar() }
529         //
530         // The problem is that the type of `x` is `&'a A`. To be
531         // well-formed, then, A must be lower-generic by `'a`, but we
532         // don't know that this holds from first principles.
533         for &(r, p) in self.region_bound_pairs {
534             debug!("generic={:?} p={:?}", generic, p);
535             if generic == p {
536                 param_bounds.push(r);
537             }
538         }
539
540         param_bounds
541     }
542
543     /// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
544     /// declared in the trait definition. For example, if the trait were
545     ///
546     /// ```rust
547     /// trait Foo<'a> {
548     ///     type Bar: 'a;
549     /// }
550     /// ```
551     ///
552     /// then this function would return `'x`. This is subject to the
553     /// limitations around higher-ranked bounds described in
554     /// `region_bounds_declared_on_associated_item`.
555     fn declared_projection_bounds_from_trait(
556         &self,
557         projection_ty: ty::ProjectionTy<'tcx>,
558     ) -> Vec<ty::Region<'tcx>> {
559         debug!("projection_bounds(projection_ty={:?})", projection_ty);
560         let mut bounds = self.region_bounds_declared_on_associated_item(projection_ty.item_def_id);
561         for r in &mut bounds {
562             *r = r.subst(self.tcx(), projection_ty.substs);
563         }
564         bounds
565     }
566
567     /// Given the def-id of an associated item, returns any region
568     /// bounds attached to that associated item from the trait definition.
569     ///
570     /// For example:
571     ///
572     /// ```rust
573     /// trait Foo<'a> {
574     ///     type Bar: 'a;
575     /// }
576     /// ```
577     ///
578     /// If we were given the def-id of `Foo::Bar`, we would return
579     /// `'a`. You could then apply the substitutions from the
580     /// projection to convert this into your namespace. This also
581     /// works if the user writes `where <Self as Foo<'a>>::Bar: 'a` on
582     /// the trait. In fact, it works by searching for just such a
583     /// where-clause.
584     ///
585     /// It will not, however, work for higher-ranked bounds like:
586     ///
587     /// ```rust
588     /// trait Foo<'a, 'b>
589     /// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
590     /// {
591     ///     type Bar;
592     /// }
593     /// ```
594     ///
595     /// This is for simplicity, and because we are not really smart
596     /// enough to cope with such bounds anywhere.
597     fn region_bounds_declared_on_associated_item(
598         &self,
599         assoc_item_def_id: DefId,
600     ) -> Vec<ty::Region<'tcx>> {
601         let tcx = self.tcx();
602         let assoc_item = tcx.associated_item(assoc_item_def_id);
603         let trait_def_id = assoc_item.container.assert_trait();
604         let trait_predicates = tcx.predicates_of(trait_def_id);
605         let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
606         let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
607         self.collect_outlives_from_predicate_list(
608             identity_proj,
609             traits::elaborate_predicates(tcx, trait_predicates.predicates),
610         )
611     }
612
613     /// Searches through a predicate list for a predicate `T: 'a`.
614     ///
615     /// Careful: does not elaborate predicates, and just uses `==`
616     /// when comparing `ty` for equality, so `ty` must be something
617     /// that does not involve inference variables and where you
618     /// otherwise want a precise match.
619     fn collect_outlives_from_predicate_list<I, P>(
620         &self,
621         ty: Ty<'tcx>,
622         predicates: I,
623     ) -> Vec<ty::Region<'tcx>>
624     where
625         I: IntoIterator<Item = P>,
626         P: AsRef<ty::Predicate<'tcx>>,
627     {
628         predicates
629             .into_iter()
630             .filter_map(|p| p.as_ref().to_opt_type_outlives())
631             .filter_map(|p| p.no_late_bound_regions())
632             .filter(|p| p.0 == ty)
633             .map(|p| p.1)
634             .collect()
635     }
636 }