@@ -62,18 +62,87 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
6262 constraints,
6363 deferred_opaque_type_errors,
6464 universal_region_relations,
65- Rc :: clone ( location_map) ,
65+ location_map,
6666 )
6767 }
6868}
6969
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+
70139pub ( crate ) fn handle_opaque_type_uses < ' tcx > (
71140 root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
72141 infcx : & BorrowckInferCtxt < ' tcx > ,
73142 constraints : & mut MirTypeckRegionConstraints < ' tcx > ,
74143 deferred_errors : & mut Vec < DeferredOpaqueTypeError < ' tcx > > ,
75144 universal_region_relations : & Frozen < UniversalRegionRelations < ' tcx > > ,
76- location_map : Rc < DenseLocationMap > ,
145+ location_map : & Rc < DenseLocationMap > ,
77146) {
78147 let opaque_types = infcx. take_opaque_types ( ) ;
79148 if opaque_types. is_empty ( ) {
@@ -97,114 +166,82 @@ pub(crate) fn handle_opaque_type_uses<'tcx>(
97166 } )
98167 . collect :: < Vec < _ > > ( ) ;
99168
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+ }
113181
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) ;
141193
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 {
146196 // Check whether the arguments are fully universal.
147197 //
148198 // FIXME: We currently treat `Opaque<'a, 'a>` as a defining use and then emit an error
149199 // as it's not fully universal. We should share this code with `check_opaque_type_parameter_valid`
150200 // 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) ] ;
152202 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 ( ) ) ) ;
162214 } else {
163- continue ' entry ;
215+ continue ' all_uses ;
164216 }
165217 }
166218 }
167219
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+ }
175222
176- let hidden_type = hidden_type. fold_with ( & mut OpaqueHiddenTypeFolder {
177- infcx,
223+ debug ! ( ?defining_uses) ;
178224
179- opaque_type_key,
180- hidden_type,
181- deferred_errors,
225+ apply_member_constraints ( ) ;
182226
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+ }
206235
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 {
208245 let Some ( expected) = root_cx. get_concrete_opaque_type ( key. def_id ) else {
209246 let guar =
210247 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>(
223260 }
224261 } ) ;
225262
263+ let universal_regions = & universal_region_relations. universal_regions ;
226264 let mut relation =
227265 EquateRegions { infcx, span : hidden_type. span , universal_regions, constraints } ;
228266 match TypeRelation :: relate ( & mut relation, hidden_type. ty , expected. ty ) {
@@ -259,23 +297,20 @@ fn to_region_vid<'tcx>(
259297}
260298
261299struct OpaqueHiddenTypeFolder < ' a , ' tcx > {
262- infcx : & ' a BorrowckInferCtxt < ' tcx > ,
300+ rcx : & ' a RegionCtxt < ' a , ' tcx > ,
301+
263302 // For diagnostics.
264303 opaque_type_key : OpaqueTypeKey < ' tcx > ,
265304 hidden_type : OpaqueHiddenType < ' tcx > ,
266305 deferred_errors : & ' a mut Vec < DeferredOpaqueTypeError < ' tcx > > ,
267306
268307 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 > ,
273308}
274309
275310impl < ' tcx > OpaqueHiddenTypeFolder < ' _ , ' tcx > {
276311 #[ instrument( level = "debug" , skip( self ) ) ]
277312 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) ;
279314 if let Some ( ( _, reg) ) = self . arg_regions . iter ( ) . copied ( ) . find ( |& ( vid, _) | vid == member_vid)
280315 {
281316 debug ! ( "member equal to arg" ) ;
@@ -284,7 +319,7 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
284319
285320 // If the member region lives in a higher universe, we currently choose
286321 // 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 ( ) {
288323 debug ! ( "member not in root universe" ) ;
289324 return None ;
290325 }
@@ -297,8 +332,8 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
297332 . iter ( )
298333 . copied ( )
299334 . 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)
302337 } )
303338 } )
304339 . collect :: < Vec < _ > > ( ) ;
@@ -312,9 +347,9 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
312347 // If we have a requirement `'upper_bound: 'member`, equating `'member`
313348 // with some region `'choice` means we now also require `'upper_bound: 'choice`.
314349 // 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) {
316351 choice_regions. retain ( |& ( choice_region, _) | {
317- self . universal_region_relations . outlives ( ub, choice_region)
352+ self . rcx . universal_region_relations . outlives ( ub, choice_region)
318353 } ) ;
319354 }
320355
@@ -333,14 +368,14 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
333368 // `['d, 'e]` are ignored because they do not compare - the same goes for `['a, 'b]`.
334369 let totally_ordered_subset = choice_regions. iter ( ) . copied ( ) . filter ( |& ( r1, _) | {
335370 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)
338373 } )
339374 } ) ;
340375 // Now we're left with `['static, 'c]`. Pick `'c` as the minimum!
341376 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) ;
344379 match ( r1_outlives_r2, r2_outlives_r1) {
345380 ( true , true ) => {
346381 if r1 < r2 {
@@ -379,7 +414,7 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
379414
380415impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for OpaqueHiddenTypeFolder < ' _ , ' tcx > {
381416 fn cx ( & self ) -> TyCtxt < ' tcx > {
382- self . infcx . tcx
417+ self . rcx . infcx . tcx
383418 }
384419
385420 fn fold_region ( & mut self , r : Region < ' tcx > ) -> Region < ' tcx > {
0 commit comments