]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/outlives/obligations.rs
5db850f1588b6a24bd4c784d56a28e64751a95a6
[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 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 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_regions());
309
310         let components = self.tcx.outlives_components(ty);
311         self.components_must_outlive(origin, components, region);
312     }
313
314     fn components_must_outlive(
315         &mut self,
316         origin: infer::SubregionOrigin<'tcx>,
317         components: Vec<Component<'tcx>>,
318         region: ty::Region<'tcx>,
319     ) {
320         for component in components {
321             let origin = origin.clone();
322             match component {
323                 Component::Region(region1) => {
324                     self.delegate
325                         .push_sub_region_constraint(origin, region, region1);
326                 }
327                 Component::Param(param_ty) => {
328                     self.param_ty_must_outlive(origin, region, param_ty);
329                 }
330                 Component::Projection(projection_ty) => {
331                     self.projection_must_outlive(origin, region, projection_ty);
332                 }
333                 Component::EscapingProjection(subcomponents) => {
334                     self.components_must_outlive(origin, subcomponents, region);
335                 }
336                 Component::UnresolvedInferenceVariable(v) => {
337                     // ignore this, we presume it will yield an error
338                     // later, since if a type variable is not resolved by
339                     // this point it never will be
340                     self.tcx.sess.delay_span_bug(
341                         origin.span(),
342                         &format!("unresolved inference variable in outlives: {:?}", v),
343                     );
344                 }
345             }
346         }
347     }
348
349     fn param_ty_must_outlive(
350         &mut self,
351         origin: infer::SubregionOrigin<'tcx>,
352         region: ty::Region<'tcx>,
353         param_ty: ty::ParamTy,
354     ) {
355         debug!(
356             "param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
357             region, param_ty, origin
358         );
359
360         let generic = GenericKind::Param(param_ty);
361         let verify_bound = self.verify_bound.generic_bound(generic);
362         self.delegate
363             .push_verify(origin, generic, region, verify_bound);
364     }
365
366     fn projection_must_outlive(
367         &mut self,
368         origin: infer::SubregionOrigin<'tcx>,
369         region: ty::Region<'tcx>,
370         projection_ty: ty::ProjectionTy<'tcx>,
371     ) {
372         debug!(
373             "projection_must_outlive(region={:?}, projection_ty={:?}, origin={:?})",
374             region, projection_ty, origin
375         );
376
377         // This case is thorny for inference. The fundamental problem is
378         // that there are many cases where we have choice, and inference
379         // doesn't like choice (the current region inference in
380         // particular). :) First off, we have to choose between using the
381         // OutlivesProjectionEnv, OutlivesProjectionTraitDef, and
382         // OutlivesProjectionComponent rules, any one of which is
383         // sufficient.  If there are no inference variables involved, it's
384         // not hard to pick the right rule, but if there are, we're in a
385         // bit of a catch 22: if we picked which rule we were going to
386         // use, we could add constraints to the region inference graph
387         // that make it apply, but if we don't add those constraints, the
388         // rule might not apply (but another rule might). For now, we err
389         // on the side of adding too few edges into the graph.
390
391         // Compute the bounds we can derive from the environment. This
392         // is an "approximate" match -- in some cases, these bounds
393         // may not apply.
394         let approx_env_bounds = self.verify_bound
395             .projection_approx_declared_bounds_from_env(projection_ty);
396         debug!(
397             "projection_must_outlive: approx_env_bounds={:?}",
398             approx_env_bounds
399         );
400
401         // Compute the bounds we can derive from the trait definition.
402         // These are guaranteed to apply, no matter the inference
403         // results.
404         let trait_bounds: Vec<_> = self.verify_bound
405             .projection_declared_bounds_from_trait(projection_ty)
406             .collect();
407
408         // If declared bounds list is empty, the only applicable rule is
409         // OutlivesProjectionComponent. If there are inference variables,
410         // then, we can break down the outlives into more primitive
411         // components without adding unnecessary edges.
412         //
413         // If there are *no* inference variables, however, we COULD do
414         // this, but we choose not to, because the error messages are less
415         // good. For example, a requirement like `T::Item: 'r` would be
416         // translated to a requirement that `T: 'r`; when this is reported
417         // to the user, it will thus say "T: 'r must hold so that T::Item:
418         // 'r holds". But that makes it sound like the only way to fix
419         // the problem is to add `T: 'r`, which isn't true. So, if there are no
420         // inference variables, we use a verify constraint instead of adding
421         // edges, which winds up enforcing the same condition.
422         let needs_infer = projection_ty.needs_infer();
423         if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
424             debug!("projection_must_outlive: no declared bounds");
425
426             for component_ty in projection_ty.substs.types() {
427                 self.type_must_outlive(origin.clone(), component_ty, region);
428             }
429
430             for r in projection_ty.substs.regions() {
431                 self.delegate
432                     .push_sub_region_constraint(origin.clone(), region, r);
433             }
434
435             return;
436         }
437
438         // If we found a unique bound `'b` from the trait, and we
439         // found nothing else from the environment, then the best
440         // action is to require that `'b: 'r`, so do that.
441         //
442         // This is best no matter what rule we use:
443         //
444         // - OutlivesProjectionEnv: these would translate to the requirement that `'b:'r`
445         // - OutlivesProjectionTraitDef: these would translate to the requirement that `'b:'r`
446         // - OutlivesProjectionComponent: this would require `'b:'r`
447         //   in addition to other conditions
448         if !trait_bounds.is_empty()
449             && trait_bounds[1..]
450                 .iter()
451                 .chain(approx_env_bounds.iter().map(|b| &b.1))
452                 .all(|b| *b == trait_bounds[0])
453         {
454             let unique_bound = trait_bounds[0];
455             debug!(
456                 "projection_must_outlive: unique trait bound = {:?}",
457                 unique_bound
458             );
459             debug!("projection_must_outlive: unique declared bound appears in trait ref");
460             self.delegate
461                 .push_sub_region_constraint(origin, region, unique_bound);
462             return;
463         }
464
465         // Fallback to verifying after the fact that there exists a
466         // declared bound, or that all the components appearing in the
467         // projection outlive; in some cases, this may add insufficient
468         // edges into the inference graph, leading to inference failures
469         // even though a satisfactory solution exists.
470         let generic = GenericKind::Projection(projection_ty);
471         let verify_bound = self.verify_bound.generic_bound(generic);
472         self.delegate
473             .push_verify(origin, generic.clone(), region, verify_bound);
474     }
475 }
476
477 impl<'cx, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'gcx, 'tcx> {
478     fn push_sub_region_constraint(
479         &mut self,
480         origin: SubregionOrigin<'tcx>,
481         a: ty::Region<'tcx>,
482         b: ty::Region<'tcx>,
483     ) {
484         self.sub_regions(origin, a, b)
485     }
486
487     fn push_verify(
488         &mut self,
489         origin: SubregionOrigin<'tcx>,
490         kind: GenericKind<'tcx>,
491         a: ty::Region<'tcx>,
492         bound: VerifyBound<'tcx>,
493     ) {
494         self.verify_generic_bound(origin, kind, a, bound)
495     }
496 }