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