]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/free_region_relations.rs
Move `{core,std}::stream::Stream` to `{core,std}::async_iter::AsyncIterator`.
[rust.git] / compiler / rustc_borrowck / src / type_check / free_region_relations.rs
1 use rustc_data_structures::frozen::Frozen;
2 use rustc_data_structures::transitive_relation::TransitiveRelation;
3 use rustc_infer::infer::canonical::QueryRegionConstraints;
4 use rustc_infer::infer::outlives;
5 use rustc_infer::infer::region_constraints::GenericKind;
6 use rustc_infer::infer::InferCtxt;
7 use rustc_middle::mir::ConstraintCategory;
8 use rustc_middle::traits::query::OutlivesBound;
9 use rustc_middle::ty::{self, RegionVid, Ty};
10 use rustc_span::DUMMY_SP;
11 use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
12 use std::rc::Rc;
13 use type_op::TypeOpOutput;
14
15 use crate::{
16     type_check::constraint_conversion,
17     type_check::{Locations, MirTypeckRegionConstraints},
18     universal_regions::UniversalRegions,
19 };
20
21 #[derive(Debug)]
22 crate struct UniversalRegionRelations<'tcx> {
23     universal_regions: Rc<UniversalRegions<'tcx>>,
24
25     /// Stores the outlives relations that are known to hold from the
26     /// implied bounds, in-scope where-clauses, and that sort of
27     /// thing.
28     outlives: TransitiveRelation<RegionVid>,
29
30     /// This is the `<=` relation; that is, if `a: b`, then `b <= a`,
31     /// and we store that here. This is useful when figuring out how
32     /// to express some local region in terms of external regions our
33     /// caller will understand.
34     inverse_outlives: TransitiveRelation<RegionVid>,
35 }
36
37 /// Each RBP `('a, GK)` indicates that `GK: 'a` can be assumed to
38 /// be true. These encode relationships like `T: 'a` that are
39 /// added via implicit bounds.
40 ///
41 /// Each region here is guaranteed to be a key in the `indices`
42 /// map. We use the "original" regions (i.e., the keys from the
43 /// map, and not the values) because the code in
44 /// `process_registered_region_obligations` has some special-cased
45 /// logic expecting to see (e.g.) `ReStatic`, and if we supplied
46 /// our special inference variable there, we would mess that up.
47 type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
48
49 /// As part of computing the free region relations, we also have to
50 /// normalize the input-output types, which we then need later. So we
51 /// return those. This vector consists of first the input types and
52 /// then the output type as the last element.
53 type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
54
55 crate struct CreateResult<'tcx> {
56     crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
57     crate region_bound_pairs: RegionBoundPairs<'tcx>,
58     crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
59 }
60
61 crate fn create<'tcx>(
62     infcx: &InferCtxt<'_, 'tcx>,
63     param_env: ty::ParamEnv<'tcx>,
64     implicit_region_bound: Option<ty::Region<'tcx>>,
65     universal_regions: &Rc<UniversalRegions<'tcx>>,
66     constraints: &mut MirTypeckRegionConstraints<'tcx>,
67 ) -> CreateResult<'tcx> {
68     UniversalRegionRelationsBuilder {
69         infcx,
70         param_env,
71         implicit_region_bound,
72         constraints,
73         universal_regions: universal_regions.clone(),
74         region_bound_pairs: Vec::new(),
75         relations: UniversalRegionRelations {
76             universal_regions: universal_regions.clone(),
77             outlives: Default::default(),
78             inverse_outlives: Default::default(),
79         },
80     }
81     .create()
82 }
83
84 impl UniversalRegionRelations<'_> {
85     /// Records in the `outlives_relation` (and
86     /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the
87     /// builder below.
88     fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) {
89         debug!("relate_universal_regions: fr_a={:?} outlives fr_b={:?}", fr_a, fr_b);
90         self.outlives.add(fr_a, fr_b);
91         self.inverse_outlives.add(fr_b, fr_a);
92     }
93
94     /// Given two universal regions, returns the postdominating
95     /// upper-bound (effectively the least upper bound).
96     ///
97     /// (See `TransitiveRelation::postdom_upper_bound` for details on
98     /// the postdominating upper bound in general.)
99     crate fn postdom_upper_bound(&self, fr1: RegionVid, fr2: RegionVid) -> RegionVid {
100         assert!(self.universal_regions.is_universal_region(fr1));
101         assert!(self.universal_regions.is_universal_region(fr2));
102         *self
103             .inverse_outlives
104             .postdom_upper_bound(&fr1, &fr2)
105             .unwrap_or(&self.universal_regions.fr_static)
106     }
107
108     /// Finds an "upper bound" for `fr` that is not local. In other
109     /// words, returns the smallest (*) known region `fr1` that (a)
110     /// outlives `fr` and (b) is not local.
111     ///
112     /// (*) If there are multiple competing choices, we return all of them.
113     crate fn non_local_upper_bounds<'a>(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> {
114         debug!("non_local_upper_bound(fr={:?})", fr);
115         let res = self.non_local_bounds(&self.inverse_outlives, fr);
116         assert!(!res.is_empty(), "can't find an upper bound!?");
117         res
118     }
119
120     /// Returns the "postdominating" bound of the set of
121     /// `non_local_upper_bounds` for the given region.
122     crate fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid {
123         let upper_bounds = self.non_local_upper_bounds(&fr);
124
125         // In case we find more than one, reduce to one for
126         // convenience.  This is to prevent us from generating more
127         // complex constraints, but it will cause spurious errors.
128         let post_dom = self.inverse_outlives.mutual_immediate_postdominator(upper_bounds);
129
130         debug!("non_local_bound: post_dom={:?}", post_dom);
131
132         post_dom
133             .and_then(|&post_dom| {
134                 // If the mutual immediate postdom is not local, then
135                 // there is no non-local result we can return.
136                 if !self.universal_regions.is_local_free_region(post_dom) {
137                     Some(post_dom)
138                 } else {
139                     None
140                 }
141             })
142             .unwrap_or(self.universal_regions.fr_static)
143     }
144
145     /// Finds a "lower bound" for `fr` that is not local. In other
146     /// words, returns the largest (*) known region `fr1` that (a) is
147     /// outlived by `fr` and (b) is not local.
148     ///
149     /// (*) If there are multiple competing choices, we pick the "postdominating"
150     /// one. See `TransitiveRelation::postdom_upper_bound` for details.
151     crate fn non_local_lower_bound(&self, fr: RegionVid) -> Option<RegionVid> {
152         debug!("non_local_lower_bound(fr={:?})", fr);
153         let lower_bounds = self.non_local_bounds(&self.outlives, &fr);
154
155         // In case we find more than one, reduce to one for
156         // convenience.  This is to prevent us from generating more
157         // complex constraints, but it will cause spurious errors.
158         let post_dom = self.outlives.mutual_immediate_postdominator(lower_bounds);
159
160         debug!("non_local_bound: post_dom={:?}", post_dom);
161
162         post_dom.and_then(|&post_dom| {
163             // If the mutual immediate postdom is not local, then
164             // there is no non-local result we can return.
165             if !self.universal_regions.is_local_free_region(post_dom) {
166                 Some(post_dom)
167             } else {
168                 None
169             }
170         })
171     }
172
173     /// Helper for `non_local_upper_bounds` and `non_local_lower_bounds`.
174     /// Repeatedly invokes `postdom_parent` until we find something that is not
175     /// local. Returns `None` if we never do so.
176     fn non_local_bounds<'a>(
177         &self,
178         relation: &'a TransitiveRelation<RegionVid>,
179         fr0: &'a RegionVid,
180     ) -> Vec<&'a RegionVid> {
181         // This method assumes that `fr0` is one of the universally
182         // quantified region variables.
183         assert!(self.universal_regions.is_universal_region(*fr0));
184
185         let mut external_parents = vec![];
186         let mut queue = vec![fr0];
187
188         // Keep expanding `fr` into its parents until we reach
189         // non-local regions.
190         while let Some(fr) = queue.pop() {
191             if !self.universal_regions.is_local_free_region(*fr) {
192                 external_parents.push(fr);
193                 continue;
194             }
195
196             queue.extend(relation.parents(fr));
197         }
198
199         debug!("non_local_bound: external_parents={:?}", external_parents);
200
201         external_parents
202     }
203
204     /// Returns `true` if fr1 is known to outlive fr2.
205     ///
206     /// This will only ever be true for universally quantified regions.
207     crate fn outlives(&self, fr1: RegionVid, fr2: RegionVid) -> bool {
208         self.outlives.contains(&fr1, &fr2)
209     }
210
211     /// Returns a vector of free regions `x` such that `fr1: x` is
212     /// known to hold.
213     crate fn regions_outlived_by(&self, fr1: RegionVid) -> Vec<&RegionVid> {
214         self.outlives.reachable_from(&fr1)
215     }
216
217     /// Returns the _non-transitive_ set of known `outlives` constraints between free regions.
218     crate fn known_outlives(&self) -> impl Iterator<Item = (&RegionVid, &RegionVid)> {
219         self.outlives.base_edges()
220     }
221 }
222
223 struct UniversalRegionRelationsBuilder<'this, 'tcx> {
224     infcx: &'this InferCtxt<'this, 'tcx>,
225     param_env: ty::ParamEnv<'tcx>,
226     universal_regions: Rc<UniversalRegions<'tcx>>,
227     implicit_region_bound: Option<ty::Region<'tcx>>,
228     constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
229
230     // outputs:
231     relations: UniversalRegionRelations<'tcx>,
232     region_bound_pairs: RegionBoundPairs<'tcx>,
233 }
234
235 impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
236     crate fn create(mut self) -> CreateResult<'tcx> {
237         let unnormalized_input_output_tys = self
238             .universal_regions
239             .unnormalized_input_tys
240             .iter()
241             .cloned()
242             .chain(Some(self.universal_regions.unnormalized_output_ty));
243
244         // For each of the input/output types:
245         // - Normalize the type. This will create some region
246         //   constraints, which we buffer up because we are
247         //   not ready to process them yet.
248         // - Then compute the implied bounds. This will adjust
249         //   the `region_bound_pairs` and so forth.
250         // - After this is done, we'll process the constraints, once
251         //   the `relations` is built.
252         let mut normalized_inputs_and_output =
253             Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
254         let constraint_sets: Vec<_> = unnormalized_input_output_tys
255             .flat_map(|ty| {
256                 debug!("build: input_or_output={:?}", ty);
257                 // We add implied bounds from both the unnormalized and normalized ty
258                 // See issue #87748
259                 let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
260                     .param_env
261                     .and(type_op::normalize::Normalize::new(ty))
262                     .fully_perform(self.infcx)
263                     .unwrap_or_else(|_| {
264                         self.infcx
265                             .tcx
266                             .sess
267                             .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
268                         TypeOpOutput {
269                             output: self.infcx.tcx.ty_error(),
270                             constraints: None,
271                             canonicalized_query: None,
272                         }
273                     });
274                 // Note: we need this in examples like
275                 // ```
276                 // trait Foo {
277                 //   type Bar;
278                 //   fn foo(&self) -> &Self::Bar;
279                 // }
280                 // impl Foo for () {
281                 //   type Bar = ();
282                 //   fn foo(&self) ->&() {}
283                 // }
284                 // ```
285                 // Both &Self::Bar and &() are WF
286                 let constraints_implied = self.add_implied_bounds(norm_ty);
287                 normalized_inputs_and_output.push(norm_ty);
288                 constraints1.into_iter().chain(constraints_implied)
289             })
290             .collect();
291
292         // Insert the facts we know from the predicates. Why? Why not.
293         let param_env = self.param_env;
294         self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
295
296         // Finally:
297         // - outlives is reflexive, so `'r: 'r` for every region `'r`
298         // - `'static: 'r` for every region `'r`
299         // - `'r: 'fn_body` for every (other) universally quantified
300         //   region `'r`, all of which are provided by our caller
301         let fr_static = self.universal_regions.fr_static;
302         let fr_fn_body = self.universal_regions.fr_fn_body;
303         for fr in self.universal_regions.universal_regions() {
304             debug!("build: relating free region {:?} to itself and to 'static", fr);
305             self.relations.relate_universal_regions(fr, fr);
306             self.relations.relate_universal_regions(fr_static, fr);
307             self.relations.relate_universal_regions(fr, fr_fn_body);
308         }
309
310         for data in &constraint_sets {
311             constraint_conversion::ConstraintConversion::new(
312                 self.infcx,
313                 &self.universal_regions,
314                 &self.region_bound_pairs,
315                 self.implicit_region_bound,
316                 self.param_env,
317                 Locations::All(DUMMY_SP),
318                 ConstraintCategory::Internal,
319                 &mut self.constraints,
320             )
321             .convert_all(data);
322         }
323
324         CreateResult {
325             universal_region_relations: Frozen::freeze(self.relations),
326             region_bound_pairs: self.region_bound_pairs,
327             normalized_inputs_and_output,
328         }
329     }
330
331     /// Update the type of a single local, which should represent
332     /// either the return type of the MIR or one of its arguments. At
333     /// the same time, compute and add any implied bounds that come
334     /// from this local.
335     fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<QueryRegionConstraints<'tcx>>> {
336         debug!("add_implied_bounds(ty={:?})", ty);
337         let TypeOpOutput { output: bounds, constraints, .. } = self
338             .param_env
339             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
340             .fully_perform(self.infcx)
341             .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
342         self.add_outlives_bounds(bounds);
343         constraints
344     }
345
346     /// Registers the `OutlivesBound` items from `outlives_bounds` in
347     /// the outlives relation as well as the region-bound pairs
348     /// listing.
349     fn add_outlives_bounds<I>(&mut self, outlives_bounds: I)
350     where
351         I: IntoIterator<Item = OutlivesBound<'tcx>>,
352     {
353         for outlives_bound in outlives_bounds {
354             debug!("add_outlives_bounds(bound={:?})", outlives_bound);
355
356             match outlives_bound {
357                 OutlivesBound::RegionSubRegion(r1, r2) => {
358                     // `where Type:` is lowered to `where Type: 'empty` so that
359                     // we check `Type` is well formed, but there's no use for
360                     // this bound here.
361                     if let ty::ReEmpty(_) = r1 {
362                         return;
363                     }
364
365                     // The bound says that `r1 <= r2`; we store `r2: r1`.
366                     let r1 = self.universal_regions.to_region_vid(r1);
367                     let r2 = self.universal_regions.to_region_vid(r2);
368                     self.relations.relate_universal_regions(r2, r1);
369                 }
370
371                 OutlivesBound::RegionSubParam(r_a, param_b) => {
372                     self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
373                 }
374
375                 OutlivesBound::RegionSubProjection(r_a, projection_b) => {
376                     self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b)));
377                 }
378             }
379         }
380     }
381 }