@@ -61,15 +61,16 @@ pub struct Constraint {
61
61
point : Location ,
62
62
}
63
63
64
- impl < ' tcx > RegionInferenceContext < ' tcx > {
64
+ impl < ' a , ' gcx , ' tcx > RegionInferenceContext < ' tcx > {
65
65
/// Creates a new region inference context with a total of
66
66
/// `num_region_variables` valid inference variables; the first N
67
67
/// of those will be constant regions representing the free
68
68
/// regions defined in `free_regions`.
69
- pub fn new ( free_regions : & FreeRegions < ' tcx > ,
70
- num_region_variables : usize ,
71
- mir : & Mir < ' tcx > )
72
- -> Self {
69
+ pub fn new (
70
+ free_regions : & FreeRegions < ' tcx > ,
71
+ num_region_variables : usize ,
72
+ mir : & Mir < ' tcx > ,
73
+ ) -> Self {
73
74
let mut result = Self {
74
75
definitions : ( 0 ..num_region_variables)
75
76
. map ( |_| RegionDefinition :: default ( ) )
@@ -83,33 +84,49 @@ impl<'tcx> RegionInferenceContext<'tcx> {
83
84
result
84
85
}
85
86
86
- fn init_free_regions ( & mut self ,
87
- free_regions : & FreeRegions < ' tcx > ,
88
- mir : & Mir < ' tcx > )
89
- {
90
- let & FreeRegions { ref indices, ref free_region_map } = free_regions;
91
-
92
- // For each free region variable X, it should contain:
93
- //
94
- // (a) the entire CFG
95
- // (b) `end(Y)` for all regions Y such that X: Y (or Y <= X)
96
- //
97
- // we add however the regions for clause (b) somewhat in
98
- // reverse, because of how the data structure in
99
- // `free_regions` is organized.
87
+ /// Initializes the region variables for each free region
88
+ /// (lifetime parameter). The first N variables always correspond
89
+ /// to the free regions appearing in the function signature (both
90
+ /// named and anonymous) and where clauses. This function iterates
91
+ /// over those regions and initializes them with minimum values.
92
+ ///
93
+ /// For example:
94
+ ///
95
+ /// fn foo<'a, 'b>(..) where 'a: 'b
96
+ ///
97
+ /// would initialize two variables like so:
98
+ ///
99
+ /// R0 = { CFG, R0 } // 'a
100
+ /// R1 = { CFG, R0, R1 } // 'b
101
+ ///
102
+ /// Here, R0 represents `'a`, and it contains (a) the entire CFG
103
+ /// and (b) any free regions that it outlives, which in this case
104
+ /// is just itself. R1 (`'b`) in contrast also outlives `'a` and
105
+ /// hence contains R0 and R1.
106
+ fn init_free_regions ( & mut self , free_regions : & FreeRegions < ' tcx > , mir : & Mir < ' tcx > ) {
107
+ let & FreeRegions {
108
+ ref indices,
109
+ ref free_region_map,
110
+ } = free_regions;
111
+
112
+ // For each free region X:
100
113
for ( free_region, index) in indices {
101
114
let variable = RegionIndex :: new ( * index) ;
102
115
103
116
self . free_regions . push ( variable) ;
104
117
118
+ // Initialize the name and a few other details.
105
119
self . definitions [ variable] . name = Some ( free_region) ;
106
120
self . definitions [ variable] . constant = true ;
107
121
108
122
// Add all nodes in the CFG to `definition.value`.
109
123
for ( block, block_data) in mir. basic_blocks ( ) . iter_enumerated ( ) {
110
124
let definition = & mut self . definitions [ variable] ;
111
- for statement_index in 0 .. block_data. statements . len ( ) + 1 {
112
- let location = Location { block, statement_index } ;
125
+ for statement_index in 0 ..block_data. statements . len ( ) + 1 {
126
+ let location = Location {
127
+ block,
128
+ statement_index,
129
+ } ;
113
130
definition. value . add_point ( location) ;
114
131
}
115
132
}
@@ -121,13 +138,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
121
138
// Y: X is true). Add `end(X)` into the set for `Y`.
122
139
for superregion in free_region_map. regions_that_outlive ( & free_region) {
123
140
let superregion_index = RegionIndex :: new ( indices[ superregion] ) ;
124
- self . definitions [ superregion_index] . value . add_free_region ( variable) ;
141
+ self . definitions [ superregion_index]
142
+ . value
143
+ . add_free_region ( variable) ;
125
144
}
126
145
127
- debug ! ( "init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`" ,
128
- free_region,
129
- variable,
130
- self . definitions[ variable] . value) ;
146
+ debug ! (
147
+ "init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`" ,
148
+ free_region,
149
+ variable,
150
+ self . definitions[ variable] . value
151
+ ) ;
131
152
}
132
153
}
133
154
@@ -157,15 +178,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
157
178
}
158
179
159
180
/// Perform region inference.
160
- pub ( super ) fn solve < ' a , ' gcx > (
161
- & mut self ,
162
- infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
163
- mir : & ' a Mir < ' tcx > ,
164
- )
165
- where
166
- ' gcx : ' tcx + ' a ,
167
- ' tcx : ' a ,
168
- {
181
+ pub ( super ) fn solve ( & mut self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > , mir : & Mir < ' tcx > ) {
182
+ self . propagate_constraints ( infcx , mir ) ;
183
+ }
184
+
185
+ /// Propagate the region constraints: this will grow the values
186
+ /// for each region variable until all the constraints are
187
+ /// satisfied. Note that some values may grow **too** large to be
188
+ /// feasible, but we check this later.
189
+ fn propagate_constraints ( & mut self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > , mir : & Mir < ' tcx > ) {
169
190
let mut changed = true ;
170
191
let mut dfs = Dfs :: new ( infcx, mir) ;
171
192
while changed {
0 commit comments