@@ -62,18 +62,87 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
62
62
constraints,
63
63
deferred_opaque_type_errors,
64
64
universal_region_relations,
65
- Rc :: clone ( location_map) ,
65
+ location_map,
66
66
)
67
67
}
68
68
}
69
69
70
+ struct RegionCtxt < ' a , ' tcx > {
71
+ infcx : & ' a BorrowckInferCtxt < ' tcx > ,
72
+ definitions : IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
73
+ universal_region_relations : & ' a UniversalRegionRelations < ' tcx > ,
74
+ constraint_sccs : ConstraintSccs ,
75
+ rev_scc_graph : ReverseSccGraph ,
76
+ scc_values : RegionValues < ConstraintSccIndex > ,
77
+ }
78
+
79
+ impl < ' a , ' tcx > RegionCtxt < ' a , ' tcx > {
80
+ fn new (
81
+ infcx : & ' a BorrowckInferCtxt < ' tcx > ,
82
+ universal_region_relations : & ' a Frozen < UniversalRegionRelations < ' tcx > > ,
83
+ location_map : Rc < DenseLocationMap > ,
84
+ constraints : & MirTypeckRegionConstraints < ' tcx > ,
85
+ ) -> RegionCtxt < ' a , ' tcx > {
86
+ let mut definitions: IndexVec < _ , _ > = infcx
87
+ . get_region_var_infos ( )
88
+ . iter ( )
89
+ . map ( |info| RegionDefinition :: new ( info. universe , info. origin ) )
90
+ . collect ( ) ;
91
+
92
+ for ( external_name, variable) in
93
+ universal_region_relations. universal_regions . named_universal_regions_iter ( )
94
+ {
95
+ definitions[ variable] . external_name = Some ( external_name) ;
96
+ }
97
+
98
+ let universal_regions = & universal_region_relations. universal_regions ;
99
+ let fr_static = universal_regions. fr_static ;
100
+ let constraint_sccs =
101
+ constraints. outlives_constraints . compute_sccs ( fr_static, & definitions) ;
102
+ let rev_scc_graph = ReverseSccGraph :: compute ( & constraint_sccs, universal_regions) ;
103
+ // Unlike the `RegionInferenceContext`, we only care about free regions
104
+ // and fully ignore liveness and placeholders.
105
+ let placeholder_indices = Default :: default ( ) ;
106
+ let mut scc_values =
107
+ RegionValues :: new ( location_map, universal_regions. len ( ) , placeholder_indices) ;
108
+ for variable in definitions. indices ( ) {
109
+ let scc = constraint_sccs. scc ( variable) ;
110
+ match definitions[ variable] . origin {
111
+ NllRegionVariableOrigin :: FreeRegion => {
112
+ scc_values. add_element ( scc, variable) ;
113
+ }
114
+ _ => { }
115
+ }
116
+ }
117
+ scc_values. propagate_constraints ( & constraint_sccs) ;
118
+
119
+ RegionCtxt {
120
+ infcx,
121
+ definitions,
122
+ universal_region_relations,
123
+ constraint_sccs,
124
+ rev_scc_graph,
125
+ scc_values,
126
+ }
127
+ }
128
+
129
+ fn representative ( & self , vid : RegionVid ) -> RegionVid {
130
+ self . constraint_sccs . scc ( vid) ;
131
+ rcx. constraint_sccs . annotation ( scc) . representative
132
+ }
133
+
134
+ fn universal_regions ( & self ) -> & UniversalRegions < ' tcx > {
135
+ & self . universal_region_relations . universal_regions
136
+ }
137
+ }
138
+
70
139
pub ( crate ) fn handle_opaque_type_uses < ' tcx > (
71
140
root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
72
141
infcx : & BorrowckInferCtxt < ' tcx > ,
73
142
constraints : & mut MirTypeckRegionConstraints < ' tcx > ,
74
143
deferred_errors : & mut Vec < DeferredOpaqueTypeError < ' tcx > > ,
75
144
universal_region_relations : & Frozen < UniversalRegionRelations < ' tcx > > ,
76
- location_map : Rc < DenseLocationMap > ,
145
+ location_map : & Rc < DenseLocationMap > ,
77
146
) {
78
147
let opaque_types = infcx. take_opaque_types ( ) ;
79
148
if opaque_types. is_empty ( ) {
@@ -97,114 +166,82 @@ pub(crate) fn handle_opaque_type_uses<'tcx>(
97
166
} )
98
167
. collect :: < Vec < _ > > ( ) ;
99
168
100
- let mut definitions: IndexVec < _ , _ > = infcx
101
- . get_region_var_infos ( )
102
- . iter ( )
103
- . map ( |info| RegionDefinition :: new ( info. universe , info. origin ) )
104
- . collect ( ) ;
105
-
106
- // Update the names (if any)
107
- // This iterator has unstable order but we collect it all into an IndexVec
108
- for ( external_name, variable) in
109
- universal_region_relations. universal_regions . named_universal_regions_iter ( )
110
- {
111
- definitions[ variable] . external_name = Some ( external_name) ;
112
- }
169
+ collect_defining_uses (
170
+ root_cx,
171
+ infcx,
172
+ constraints,
173
+ deferred_errors,
174
+ universal_region_relations,
175
+ location_map,
176
+ & mut opaque_types,
177
+ ) ;
178
+
179
+ apply_defining_uses ( root_cx, infcx, constraints, universal_region_relations, & opaque_types) ;
180
+ }
113
181
114
- let universal_regions = & universal_region_relations. universal_regions ;
115
- let fr_static = universal_regions. fr_static ;
116
- let constraint_sccs = & constraints. outlives_constraints . compute_sccs ( fr_static, & definitions) ;
117
- let rev_scc_graph = & ReverseSccGraph :: compute ( & constraint_sccs, universal_regions) ;
118
- // Unlike the `RegionInferenceContext`, we only care about free regions
119
- // and fully ignore liveness and placeholders.
120
- let placeholder_indices = Default :: default ( ) ;
121
- let mut scc_values =
122
- RegionValues :: new ( location_map, universal_regions. len ( ) , placeholder_indices) ;
123
- for variable in definitions. indices ( ) {
124
- let scc = constraint_sccs. scc ( variable) ;
125
- match definitions[ variable] . origin {
126
- NllRegionVariableOrigin :: FreeRegion => {
127
- scc_values. add_element ( scc, variable) ;
128
- }
129
- _ => { }
130
- }
131
- }
132
- scc_values. propagate_constraints ( & constraint_sccs) ;
133
- for entry in & mut opaque_types {
134
- // Map all opaque types to their SCC representatives.
135
- * entry = fold_regions ( tcx, * entry, |r, _| {
136
- let scc = constraint_sccs. scc ( r. as_var ( ) ) ;
137
- let vid = constraint_sccs. annotation ( scc) . representative ;
138
- Region :: new_var ( tcx, vid)
139
- } )
140
- }
182
+ fn collect_defining_uses < ' tcx > (
183
+ root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
184
+ infcx : & BorrowckInferCtxt < ' tcx > ,
185
+ constraints : & mut MirTypeckRegionConstraints < ' tcx > ,
186
+ deferred_errors : & mut Vec < DeferredOpaqueTypeError < ' tcx > > ,
187
+ universal_region_relations : & Frozen < UniversalRegionRelations < ' tcx > > ,
188
+ location_map : & Rc < DenseLocationMap > ,
189
+ opaque_types : & [ ( OpaqueTypeKey < ' tcx > , OpaqueHiddenType < ' tcx > ) ] ,
190
+ ) {
191
+ let tcx = infcx. tcx ;
192
+ let rcx = RegionCtxt :: new ( infcx, universal_region_relations, Rc :: clone ( location_map) , constraints) ;
141
193
142
- // We start by looking for defining uses of the opaque. These are uses where all arguments
143
- // of the opaque are free regions. We apply "member constraints" to its hidden region and
144
- // map the hidden type to the definition site of the opaque.
145
- ' entry: for & ( opaque_type_key, hidden_type) in & opaque_types {
194
+ let mut defining_uses = vec ! [ ] ;
195
+ ' all_uses: for & ( opaque_type_key, hidden_type) in opaque_types {
146
196
// Check whether the arguments are fully universal.
147
197
//
148
198
// FIXME: We currently treat `Opaque<'a, 'a>` as a defining use and then emit an error
149
199
// as it's not fully universal. We should share this code with `check_opaque_type_parameter_valid`
150
200
// to only consider actual defining uses as defining.
151
- let mut arg_regions = vec ! [ ( universal_regions. fr_static, tcx. lifetimes. re_static) ] ;
201
+ let mut arg_regions = vec ! [ ( rcx . universal_regions( ) . fr_static, tcx. lifetimes. re_static) ] ;
152
202
for ( _idx, captured_arg) in opaque_type_key. iter_captured_args ( tcx) {
153
- if let Some ( region) = captured_arg. as_region ( ) {
154
- let vid = region. as_var ( ) ;
155
- if matches ! ( definitions[ vid] . origin, NllRegionVariableOrigin :: FreeRegion )
156
- && !matches ! (
157
- universal_regions. region_classification( vid) ,
158
- Some ( RegionClassification :: External )
159
- )
160
- {
161
- arg_regions. push ( ( vid, definitions[ vid] . external_name . unwrap ( ) ) ) ;
203
+ if let Some ( r) = captured_arg. as_region ( ) {
204
+ let vid = rcx. representative ( r. as_var ( ) ) ;
205
+ let is_non_external_free_region =
206
+ matches ! ( rcx. definitions[ vid] . origin, NllRegionVariableOrigin :: FreeRegion )
207
+ && !matches ! (
208
+ rcx. universal_regions( ) . region_classification( vid) ,
209
+ Some ( RegionClassification :: External )
210
+ ) ;
211
+
212
+ if is_non_external_free_region {
213
+ arg_regions. push ( ( vid, rcx. definitions [ vid] . external_name . unwrap ( ) ) ) ;
162
214
} else {
163
- continue ' entry ;
215
+ continue ' all_uses ;
164
216
}
165
217
}
166
218
}
167
219
168
- debug ! ( ?opaque_type_key, ?hidden_type, "check defining use" ) ;
169
-
170
- let opaque_type_key = opaque_type_key. fold_captured_lifetime_args ( tcx, |region| {
171
- let vid = region. as_var ( ) ;
172
- assert ! ( matches!( definitions[ vid] . origin, NllRegionVariableOrigin :: FreeRegion ) ) ;
173
- definitions[ vid] . external_name . unwrap ( )
174
- } ) ;
220
+ defining_uses. push ( ( opaque_type_key, arg_regions, hidden_type) )
221
+ }
175
222
176
- let hidden_type = hidden_type. fold_with ( & mut OpaqueHiddenTypeFolder {
177
- infcx,
223
+ debug ! ( ?defining_uses) ;
178
224
179
- opaque_type_key,
180
- hidden_type,
181
- deferred_errors,
225
+ apply_member_constraints ( ) ;
182
226
183
- arg_regions : & arg_regions,
184
- universal_region_relations,
185
- constraint_sccs,
186
- rev_scc_graph,
187
- scc_values : & scc_values,
188
- } ) ;
189
-
190
- let ty = infcx
191
- . infer_opaque_definition_from_instantiation ( opaque_type_key, hidden_type)
192
- . unwrap_or_else ( |err| {
193
- deferred_errors. push ( DeferredOpaqueTypeError :: InvalidOpaqueTypeArgs ( err) ) ;
194
- Ty :: new_error_with_message (
195
- tcx,
196
- hidden_type. span ,
197
- "deferred invalid opaque type args" ,
198
- )
199
- } ) ;
200
-
201
- root_cx. add_concrete_opaque_type (
202
- opaque_type_key. def_id ,
203
- OpaqueHiddenType { span : hidden_type. span , ty } ,
204
- ) ;
205
- }
227
+ // Applying member constraints may add new region constraints, so we
228
+ // need to recompute the region context before actually mapping the defining
229
+ // uses to the definition site.
230
+ //
231
+ // FIXME: We should be able to partially reuse and optimize this.
232
+ let rcx = RegionCtxt :: new ( infcx, universal_region_relations, Rc :: clone ( location_map) , constraints)
233
+ map_defining_uses_to_definition_site ( ) ;
234
+ }
206
235
207
- for & ( key, hidden_type) in & opaque_types {
236
+ fn apply_defining_uses < ' tcx > (
237
+ root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
238
+ infcx : & BorrowckInferCtxt < ' tcx > ,
239
+ constraints : & mut MirTypeckRegionConstraints < ' tcx > ,
240
+ universal_region_relations : & Frozen < UniversalRegionRelations < ' tcx > > ,
241
+ opaque_types : & [ ( OpaqueTypeKey < ' tcx > , OpaqueHiddenType < ' tcx > ) ] ,
242
+ ) {
243
+ let tcx = infcx. tcx ;
244
+ for & ( key, hidden_type) in opaque_types {
208
245
let Some ( expected) = root_cx. get_concrete_opaque_type ( key. def_id ) else {
209
246
let guar =
210
247
tcx. dcx ( ) . span_err ( hidden_type. span , "non-defining use in the defining scope" ) ;
@@ -223,6 +260,7 @@ pub(crate) fn handle_opaque_type_uses<'tcx>(
223
260
}
224
261
} ) ;
225
262
263
+ let universal_regions = & universal_region_relations. universal_regions ;
226
264
let mut relation =
227
265
EquateRegions { infcx, span : hidden_type. span , universal_regions, constraints } ;
228
266
match TypeRelation :: relate ( & mut relation, hidden_type. ty , expected. ty ) {
@@ -259,23 +297,20 @@ fn to_region_vid<'tcx>(
259
297
}
260
298
261
299
struct OpaqueHiddenTypeFolder < ' a , ' tcx > {
262
- infcx : & ' a BorrowckInferCtxt < ' tcx > ,
300
+ rcx : & ' a RegionCtxt < ' a , ' tcx > ,
301
+
263
302
// For diagnostics.
264
303
opaque_type_key : OpaqueTypeKey < ' tcx > ,
265
304
hidden_type : OpaqueHiddenType < ' tcx > ,
266
305
deferred_errors : & ' a mut Vec < DeferredOpaqueTypeError < ' tcx > > ,
267
306
268
307
arg_regions : & ' a [ ( RegionVid , Region < ' tcx > ) ] ,
269
- universal_region_relations : & ' a UniversalRegionRelations < ' tcx > ,
270
- constraint_sccs : & ' a ConstraintSccs ,
271
- rev_scc_graph : & ' a ReverseSccGraph ,
272
- scc_values : & ' a RegionValues < ConstraintSccIndex > ,
273
308
}
274
309
275
310
impl < ' tcx > OpaqueHiddenTypeFolder < ' _ , ' tcx > {
276
311
#[ instrument( level = "debug" , skip( self ) ) ]
277
312
fn apply_member_constraint ( & mut self , member_vid : RegionVid ) -> Option < Region < ' tcx > > {
278
- let member = self . constraint_sccs . scc ( member_vid) ;
313
+ let member = self . rcx . constraint_sccs . scc ( member_vid) ;
279
314
if let Some ( ( _, reg) ) = self . arg_regions . iter ( ) . copied ( ) . find ( |& ( vid, _) | vid == member_vid)
280
315
{
281
316
debug ! ( "member equal to arg" ) ;
@@ -284,7 +319,7 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
284
319
285
320
// If the member region lives in a higher universe, we currently choose
286
321
// the most conservative option by leaving it unchanged.
287
- if !self . constraint_sccs . annotation ( member) . min_universe ( ) . is_root ( ) {
322
+ if !self . rcx . constraint_sccs . annotation ( member) . min_universe ( ) . is_root ( ) {
288
323
debug ! ( "member not in root universe" ) ;
289
324
return None ;
290
325
}
@@ -297,8 +332,8 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
297
332
. iter ( )
298
333
. copied ( )
299
334
. filter ( |& ( choice_region, _) | {
300
- self . scc_values . universal_regions_outlived_by ( member) . all ( |lower_bound| {
301
- self . universal_region_relations . outlives ( choice_region, lower_bound)
335
+ self . rcx . scc_values . universal_regions_outlived_by ( member) . all ( |lower_bound| {
336
+ self . rcx . universal_region_relations . outlives ( choice_region, lower_bound)
302
337
} )
303
338
} )
304
339
. collect :: < Vec < _ > > ( ) ;
@@ -312,9 +347,9 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
312
347
// If we have a requirement `'upper_bound: 'member`, equating `'member`
313
348
// with some region `'choice` means we now also require `'upper_bound: 'choice`.
314
349
// Avoid choice regions for which this does not hold.
315
- for ub in self . rev_scc_graph . upper_bounds ( member) {
350
+ for ub in self . rcx . rev_scc_graph . upper_bounds ( member) {
316
351
choice_regions. retain ( |& ( choice_region, _) | {
317
- self . universal_region_relations . outlives ( ub, choice_region)
352
+ self . rcx . universal_region_relations . outlives ( ub, choice_region)
318
353
} ) ;
319
354
}
320
355
@@ -333,14 +368,14 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
333
368
// `['d, 'e]` are ignored because they do not compare - the same goes for `['a, 'b]`.
334
369
let totally_ordered_subset = choice_regions. iter ( ) . copied ( ) . filter ( |& ( r1, _) | {
335
370
choice_regions. iter ( ) . all ( |& ( r2, _) | {
336
- self . universal_region_relations . outlives ( r1, r2)
337
- || self . universal_region_relations . outlives ( r2, r1)
371
+ self . rcx . universal_region_relations . outlives ( r1, r2)
372
+ || self . rcx . universal_region_relations . outlives ( r2, r1)
338
373
} )
339
374
} ) ;
340
375
// Now we're left with `['static, 'c]`. Pick `'c` as the minimum!
341
376
let Some ( ( _, min_choice) ) = totally_ordered_subset. reduce ( |( r1, r1_reg) , ( r2, r2_reg) | {
342
- let r1_outlives_r2 = self . universal_region_relations . outlives ( r1, r2) ;
343
- let r2_outlives_r1 = self . universal_region_relations . outlives ( r2, r1) ;
377
+ let r1_outlives_r2 = self . rcx . universal_region_relations . outlives ( r1, r2) ;
378
+ let r2_outlives_r1 = self . rcx . universal_region_relations . outlives ( r2, r1) ;
344
379
match ( r1_outlives_r2, r2_outlives_r1) {
345
380
( true , true ) => {
346
381
if r1 < r2 {
@@ -379,7 +414,7 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
379
414
380
415
impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for OpaqueHiddenTypeFolder < ' _ , ' tcx > {
381
416
fn cx ( & self ) -> TyCtxt < ' tcx > {
382
- self . infcx . tcx
417
+ self . rcx . infcx . tcx
383
418
}
384
419
385
420
fn fold_region ( & mut self , r : Region < ' tcx > ) -> Region < ' tcx > {
0 commit comments