1 use crate::infer::free_regions::FreeRegionMap;
2 use crate::infer::{GenericKind, InferCtxt};
3 use crate::traits::query::OutlivesBound;
4 use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
6 use super::explicit_outlives_bounds;
8 /// The `OutlivesEnvironment` collects information about what outlives
9 /// what in a given type-checking setting. For example, if we have a
10 /// where-clause like `where T: 'a` in scope, then the
11 /// `OutlivesEnvironment` would record that (in its
12 /// `region_bound_pairs` field). Similarly, it contains methods for
13 /// processing and adding implied bounds into the outlives
16 /// Other code at present does not typically take a
17 /// `&OutlivesEnvironment`, but rather takes some of its fields (e.g.,
18 /// `process_registered_region_obligations` wants the
19 /// region-bound-pairs). There is no mistaking it: the current setup
20 /// of tracking region information is quite scattered! The
21 /// `OutlivesEnvironment`, for example, needs to sometimes be combined
22 /// with the `middle::RegionRelations`, to yield a full picture of how
23 /// (lexical) lifetimes interact. However, I'm reluctant to do more
24 /// refactoring here, since the setup with NLL is quite different.
25 /// For example, NLL has no need of `RegionRelations`, and is solely
26 /// interested in the `OutlivesEnvironment`. -nmatsakis
28 pub struct OutlivesEnvironment<'tcx> {
29 pub param_env: ty::ParamEnv<'tcx>,
30 free_region_map: FreeRegionMap<'tcx>,
32 // Contains the implied region bounds in scope for our current body.
37 // fn foo<'a, 'b, T>(x: &'a T, y: &'b ()) {
38 // bar(x, y, |y: &'b T| { .. } // body B1)
42 // Here, when checking the body B0, the list would be `[T: 'a]`, because we
43 // infer that `T` must outlive `'a` from the implied bounds on the
46 // For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we
47 // also can see that -- within the closure body! -- `T` must
48 // outlive `'b`. This is not necessarily true outside the closure
49 // body, since the closure may never be called.
50 region_bound_pairs: RegionBoundPairs<'tcx>,
53 /// "Region-bound pairs" tracks outlives relations that are known to
54 /// be true, either because of explicit where-clauses like `T: 'a` or
55 /// because of implied bounds.
56 pub type RegionBoundPairs<'tcx> = Vec<(Region<'tcx>, GenericKind<'tcx>)>;
58 impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
59 pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
60 let mut env = OutlivesEnvironment {
62 free_region_map: Default::default(),
63 region_bound_pairs: Default::default(),
66 env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
71 /// Borrows current value of the `free_region_map`.
72 pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
76 /// Borrows current `region_bound_pairs`.
77 pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
78 &self.region_bound_pairs
81 /// Processes outlives bounds that are known to hold, whether from implied or other sources.
83 /// The `infcx` parameter is optional; if the implied bounds may
84 /// contain inference variables, it must be supplied, in which
85 /// case we will register "givens" on the inference context. (See
86 /// `RegionConstraintData`.)
87 pub fn add_outlives_bounds<I>(
89 infcx: Option<&InferCtxt<'a, 'tcx>>,
92 I: IntoIterator<Item = OutlivesBound<'tcx>>,
94 // Record relationships such as `T:'x` that don't go into the
95 // free-region-map but which we use here.
96 for outlives_bound in outlives_bounds {
97 debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
98 match outlives_bound {
99 OutlivesBound::RegionSubParam(r_a, param_b) => {
100 self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
102 OutlivesBound::RegionSubProjection(r_a, projection_b) => {
103 self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b)));
105 OutlivesBound::RegionSubRegion(r_a, r_b) => {
106 if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
108 .expect("no infcx provided but region vars found")
109 .add_given(r_a, vid_b);
111 // In principle, we could record (and take
112 // advantage of) every relationship here, but
113 // we are also free not to -- it simply means
114 // strictly less that we can successfully type
115 // check. Right now we only look for things
116 // relationships between free regions. (It may
117 // also be that we should revise our inference
118 // system to be more general and to make use
119 // of *every* relationship that arises here,
120 // but presently we do not.)
121 self.free_region_map.relate_regions(r_a, r_b);