]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/outlives/env.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / outlives / env.rs
CommitLineData
f9f354fc 1use crate::infer::free_regions::FreeRegionMap;
9fa01778 2use crate::infer::{GenericKind, InferCtxt};
ba9703b0 3use crate::traits::query::OutlivesBound;
064997fb 4use rustc_data_structures::fx::FxIndexSet;
5099ac24 5use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
ba9703b0
XL
6
7use 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)]
29pub 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
57pub type RegionBoundPairs<'tcx> =
58 FxIndexSet<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>;
0bf4aa26 59
dc9dc135 60impl<'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}