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