]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/outlives/obligations.rs
502a5828f3ea5c68109a389f4b9e27c38c13c430
[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 `push_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 infer::outlives::env::RegionBoundPairs;
73 use infer::outlives::verify::VerifyBoundCx;
74 use infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
75 use rustc_data_structures::fx::FxHashMap;
76 use syntax::ast;
77 use traits::ObligationCause;
78 use ty::outlives::Component;
79 use ty::{self, Region, Ty, TyCtxt, TypeFoldable};
80
81 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
82     /// Registers that the given region obligation must be resolved
83     /// from within the scope of `body_id`. These regions are enqueued
84     /// and later processed by regionck, when full type information is
85     /// available (see `region_obligations` field for more
86     /// information).
87     pub fn register_region_obligation(
88         &self,
89         body_id: ast::NodeId,
90         obligation: RegionObligation<'tcx>,
91     ) {
92         debug!(
93             "register_region_obligation(body_id={:?}, obligation={:?})",
94             body_id, obligation
95         );
96
97         self.region_obligations
98             .borrow_mut()
99             .push((body_id, obligation));
100     }
101
102     pub fn register_region_obligation_with_cause(
103         &self,
104         sup_type: Ty<'tcx>,
105         sub_region: Region<'tcx>,
106         cause: &ObligationCause<'tcx>,
107     ) {
108         let origin = SubregionOrigin::from_obligation_cause(cause, || {
109             infer::RelateParamBound(cause.span, sup_type)
110         });
111
112         self.register_region_obligation(
113             cause.body_id,
114             RegionObligation {
115                 sup_type,
116                 sub_region,
117                 origin,
118             },
119         );
120     }
121
122     /// Trait queries just want to pass back type obligations "as is"
123     pub fn take_registered_region_obligations(&self) -> Vec<(ast::NodeId, RegionObligation<'tcx>)> {
124         ::std::mem::replace(&mut *self.region_obligations.borrow_mut(), vec![])
125     }
126
127     /// Process the region obligations that must be proven (during
128     /// `regionck`) for the given `body_id`, given information about
129     /// the region bounds in scope and so forth. This function must be
130     /// invoked for all relevant body-ids before region inference is
131     /// done (or else an assert will fire).
132     ///
133     /// See the `region_obligations` field of `InferCtxt` for some
134     /// comments about how this function fits into the overall expected
135     /// flow of the inferencer. The key point is that it is
136     /// invoked after all type-inference variables have been bound --
137     /// towards the end of regionck. This also ensures that the
138     /// region-bound-pairs are available (see comments above regarding
139     /// closures).
140     ///
141     /// # Parameters
142     ///
143     /// - `region_bound_pairs`: the set of region bounds implied by
144     ///   the parameters and where-clauses. In particular, each pair
145     ///   `('a, K)` in this list tells us that the bounds in scope
146     ///   indicate that `K: 'a`, where `K` is either a generic
147     ///   parameter like `T` or a projection like `T::Item`.
148     /// - `implicit_region_bound`: if some, this is a region bound
149     ///   that is considered to hold for all type parameters (the
150     ///   function body).
151     /// - `param_env` is the parameter environment for the enclosing function.
152     /// - `body_id` is the body-id whose region obligations are being
153     ///   processed.
154     ///
155     /// # Returns
156     ///
157     /// This function may have to perform normalizations, and hence it
158     /// returns an `InferOk` with subobligations that must be
159     /// processed.
160     pub fn process_registered_region_obligations(
161         &self,
162         region_bound_pairs_map: &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
163         implicit_region_bound: Option<ty::Region<'tcx>>,
164         param_env: ty::ParamEnv<'tcx>,
165     ) {
166         assert!(
167             !self.in_snapshot.get(),
168             "cannot process registered region obligations in a snapshot"
169         );
170
171         debug!("process_registered_region_obligations()");
172
173         let my_region_obligations = self.take_registered_region_obligations();
174
175         for (
176             body_id,
177             RegionObligation {
178                 sup_type,
179                 sub_region,
180                 origin,
181             },
182         ) in my_region_obligations
183         {
184             debug!(
185                 "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
186                 sup_type, sub_region, origin
187             );
188
189             let sup_type = self.resolve_type_vars_if_possible(&sup_type);
190
191             if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
192                 let outlives = &mut TypeOutlives::new(
193                     self,
194                     self.tcx,
195                     &region_bound_pairs,
196                     implicit_region_bound,
197                     param_env,
198                 );
199                 outlives.type_must_outlive(origin, sup_type, sub_region);
200             } else {
201                 self.tcx.sess.delay_span_bug(
202                     origin.span(),
203                     &format!("no region-bound-pairs for {:?}", body_id),
204                 )
205             }
206         }
207     }
208
209     /// Processes a single ad-hoc region obligation that was not
210     /// registered in advance.
211     pub fn type_must_outlive(
212         &self,
213         region_bound_pairs: &RegionBoundPairs<'tcx>,
214         implicit_region_bound: Option<ty::Region<'tcx>>,
215         param_env: ty::ParamEnv<'tcx>,
216         origin: infer::SubregionOrigin<'tcx>,
217         ty: Ty<'tcx>,
218         region: ty::Region<'tcx>,
219     ) {
220         let outlives = &mut TypeOutlives::new(
221             self,
222             self.tcx,
223             region_bound_pairs,
224             implicit_region_bound,
225             param_env,
226         );
227         let ty = self.resolve_type_vars_if_possible(&ty);
228         outlives.type_must_outlive(origin, ty, region);
229     }
230 }
231
232 /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
233 /// obligation into a series of `'a: 'b` constraints and "verifys", as
234 /// described on the module comment. The final constraints are emitted
235 /// via a "delegate" of type `D` -- this is usually the `infcx`, which
236 /// accrues them into the `region_obligations` code, but for NLL we
237 /// use something else.
238 pub struct TypeOutlives<'cx, 'gcx: 'tcx, 'tcx: 'cx, D>
239 where
240     D: TypeOutlivesDelegate<'tcx>,
241 {
242     // See the comments on `process_registered_region_obligations` for the meaning
243     // of these fields.
244     delegate: D,
245     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
246     verify_bound: VerifyBoundCx<'cx, 'gcx, 'tcx>,
247 }
248
249 pub trait TypeOutlivesDelegate<'tcx> {
250     fn push_sub_region_constraint(
251         &mut self,
252         origin: SubregionOrigin<'tcx>,
253         a: ty::Region<'tcx>,
254         b: ty::Region<'tcx>,
255     );
256
257     fn push_verify(
258         &mut self,
259         origin: SubregionOrigin<'tcx>,
260         kind: GenericKind<'tcx>,
261         a: ty::Region<'tcx>,
262         bound: VerifyBound<'tcx>,
263     );
264 }
265
266 impl<'cx, 'gcx, 'tcx, D> TypeOutlives<'cx, 'gcx, 'tcx, D>
267 where
268     D: TypeOutlivesDelegate<'tcx>,
269 {
270     pub fn new(
271         delegate: D,
272         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
273         region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
274         implicit_region_bound: Option<ty::Region<'tcx>>,
275         param_env: ty::ParamEnv<'tcx>,
276     ) -> Self {
277         Self {
278             delegate,
279             tcx,
280             verify_bound: VerifyBoundCx::new(
281                 tcx,
282                 region_bound_pairs,
283                 implicit_region_bound,
284                 param_env,
285             ),
286         }
287     }
288
289     /// Adds constraints to inference such that `T: 'a` holds (or
290     /// reports an error if it cannot).
291     ///
292     /// # Parameters
293     ///
294     /// - `origin`, the reason we need this constraint
295     /// - `ty`, the type `T`
296     /// - `region`, the region `'a`
297     pub fn type_must_outlive(
298         &mut self,
299         origin: infer::SubregionOrigin<'tcx>,
300         ty: Ty<'tcx>,
301         region: ty::Region<'tcx>,
302     ) {
303         debug!(
304             "type_must_outlive(ty={:?}, region={:?}, origin={:?})",
305             ty, region, origin
306         );
307
308         assert!(!ty.has_escaping_bound_vars());
309
310         let mut components = smallvec![];
311         self.tcx.push_outlives_components(ty, &mut components);
312         self.components_must_outlive(origin, &components, region);
313     }
314
315     fn components_must_outlive(
316         &mut self,
317         origin: infer::SubregionOrigin<'tcx>,
318         components: &[Component<'tcx>],
319         region: ty::Region<'tcx>,
320     ) {
321         for component in components.iter() {
322             let origin = origin.clone();
323             match component {
324                 Component::Region(region1) => {
325                     self.delegate
326                         .push_sub_region_constraint(origin, region, region1);
327                 }
328                 Component::Param(param_ty) => {
329                     self.param_ty_must_outlive(origin, region, *param_ty);
330                 }
331                 Component::Projection(projection_ty) => {
332                     self.projection_must_outlive(origin, region, *projection_ty);
333                 }
334                 Component::EscapingProjection(subcomponents) => {
335                     self.components_must_outlive(origin, &subcomponents, region);
336                 }
337                 Component::UnresolvedInferenceVariable(v) => {
338                     // ignore this, we presume it will yield an error
339                     // later, since if a type variable is not resolved by
340                     // this point it never will be
341                     self.tcx.sess.delay_span_bug(
342                         origin.span(),
343                         &format!("unresolved inference variable in outlives: {:?}", v),
344                     );
345                 }
346             }
347         }
348     }
349
350     fn param_ty_must_outlive(
351         &mut self,
352         origin: infer::SubregionOrigin<'tcx>,
353         region: ty::Region<'tcx>,
354         param_ty: ty::ParamTy,
355     ) {
356         debug!(
357             "param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
358             region, param_ty, origin
359         );
360
361         let generic = GenericKind::Param(param_ty);
362         let verify_bound = self.verify_bound.generic_bound(generic);
363         self.delegate
364             .push_verify(origin, generic, region, verify_bound);
365     }
366
367     fn projection_must_outlive(
368         &mut self,
369         origin: infer::SubregionOrigin<'tcx>,
370         region: ty::Region<'tcx>,
371         projection_ty: ty::ProjectionTy<'tcx>,
372     ) {
373         debug!(
374             "projection_must_outlive(region={:?}, projection_ty={:?}, origin={:?})",
375             region, projection_ty, origin
376         );
377
378         // This case is thorny for inference. The fundamental problem is
379         // that there are many cases where we have choice, and inference
380         // doesn't like choice (the current region inference in
381         // particular). :) First off, we have to choose between using the
382         // OutlivesProjectionEnv, OutlivesProjectionTraitDef, and
383         // OutlivesProjectionComponent rules, any one of which is
384         // sufficient.  If there are no inference variables involved, it's
385         // not hard to pick the right rule, but if there are, we're in a
386         // bit of a catch 22: if we picked which rule we were going to
387         // use, we could add constraints to the region inference graph
388         // that make it apply, but if we don't add those constraints, the
389         // rule might not apply (but another rule might). For now, we err
390         // on the side of adding too few edges into the graph.
391
392         // Compute the bounds we can derive from the trait definition.
393         // These are guaranteed to apply, no matter the inference
394         // results.
395         let trait_bounds: Vec<_> = self.verify_bound
396             .projection_declared_bounds_from_trait(projection_ty)
397             .collect();
398
399         // Compute the bounds we can derive from the environment. This
400         // is an "approximate" match -- in some cases, these bounds
401         // may not apply.
402         let mut approx_env_bounds = self.verify_bound
403             .projection_approx_declared_bounds_from_env(projection_ty);
404         debug!(
405             "projection_must_outlive: approx_env_bounds={:?}",
406             approx_env_bounds
407         );
408
409         // Remove outlives bounds that we get from the environment but
410         // which are also deducable from the trait. This arises (cc
411         // #55756) in cases where you have e.g. `<T as Foo<'a>>::Item:
412         // 'a` in the environment but `trait Foo<'b> { type Item: 'b
413         // }` in the trait definition.
414         approx_env_bounds.retain(|bound| {
415             match bound.0.sty {
416                 ty::Projection(projection_ty) => {
417                     self.verify_bound.projection_declared_bounds_from_trait(projection_ty)
418                         .all(|r| r != bound.1)
419                 }
420
421                 _ => panic!("expected only projection types from env, not {:?}", bound.0),
422             }
423         });
424
425         // If declared bounds list is empty, the only applicable rule is
426         // OutlivesProjectionComponent. If there are inference variables,
427         // then, we can break down the outlives into more primitive
428         // components without adding unnecessary edges.
429         //
430         // If there are *no* inference variables, however, we COULD do
431         // this, but we choose not to, because the error messages are less
432         // good. For example, a requirement like `T::Item: 'r` would be
433         // translated to a requirement that `T: 'r`; when this is reported
434         // to the user, it will thus say "T: 'r must hold so that T::Item:
435         // 'r holds". But that makes it sound like the only way to fix
436         // the problem is to add `T: 'r`, which isn't true. So, if there are no
437         // inference variables, we use a verify constraint instead of adding
438         // edges, which winds up enforcing the same condition.
439         let needs_infer = projection_ty.needs_infer();
440         if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
441             debug!("projection_must_outlive: no declared bounds");
442
443             for component_ty in projection_ty.substs.types() {
444                 self.type_must_outlive(origin.clone(), component_ty, region);
445             }
446
447             for r in projection_ty.substs.regions() {
448                 self.delegate
449                     .push_sub_region_constraint(origin.clone(), region, r);
450             }
451
452             return;
453         }
454
455         // If we found a unique bound `'b` from the trait, and we
456         // found nothing else from the environment, then the best
457         // action is to require that `'b: 'r`, so do that.
458         //
459         // This is best no matter what rule we use:
460         //
461         // - OutlivesProjectionEnv: these would translate to the requirement that `'b:'r`
462         // - OutlivesProjectionTraitDef: these would translate to the requirement that `'b:'r`
463         // - OutlivesProjectionComponent: this would require `'b:'r`
464         //   in addition to other conditions
465         if !trait_bounds.is_empty()
466             && trait_bounds[1..]
467                 .iter()
468                 .chain(approx_env_bounds.iter().map(|b| &b.1))
469                 .all(|b| *b == trait_bounds[0])
470         {
471             let unique_bound = trait_bounds[0];
472             debug!(
473                 "projection_must_outlive: unique trait bound = {:?}",
474                 unique_bound
475             );
476             debug!("projection_must_outlive: unique declared bound appears in trait ref");
477             self.delegate
478                 .push_sub_region_constraint(origin, region, unique_bound);
479             return;
480         }
481
482         // Fallback to verifying after the fact that there exists a
483         // declared bound, or that all the components appearing in the
484         // projection outlive; in some cases, this may add insufficient
485         // edges into the inference graph, leading to inference failures
486         // even though a satisfactory solution exists.
487         let generic = GenericKind::Projection(projection_ty);
488         let verify_bound = self.verify_bound.generic_bound(generic);
489         self.delegate
490             .push_verify(origin, generic.clone(), region, verify_bound);
491     }
492 }
493
494 impl<'cx, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'gcx, 'tcx> {
495     fn push_sub_region_constraint(
496         &mut self,
497         origin: SubregionOrigin<'tcx>,
498         a: ty::Region<'tcx>,
499         b: ty::Region<'tcx>,
500     ) {
501         self.sub_regions(origin, a, b)
502     }
503
504     fn push_verify(
505         &mut self,
506         origin: SubregionOrigin<'tcx>,
507         kind: GenericKind<'tcx>,
508         a: ty::Region<'tcx>,
509         bound: VerifyBound<'tcx>,
510     ) {
511         self.verify_generic_bound(origin, kind, a, bound)
512     }
513 }