@@ -13,8 +13,9 @@ use rustc_hir::def_id::DefId;
13
13
use rustc_hir:: hir_id:: HirIdSet ;
14
14
use rustc_hir:: intravisit:: { self , Visitor } ;
15
15
use rustc_hir:: { Arm , Expr , ExprKind , Guard , HirId , Pat , PatKind } ;
16
+ use rustc_infer:: infer:: RegionVariableOrigin ;
16
17
use rustc_middle:: middle:: region:: { self , Scope , ScopeData , YieldData } ;
17
- use rustc_middle:: ty:: { self , RvalueScopes , Ty , TyCtxt , TypeVisitable } ;
18
+ use rustc_middle:: ty:: { self , BoundVariableKind , RvalueScopes , Ty , TyCtxt , TypeVisitable } ;
18
19
use rustc_span:: symbol:: sym;
19
20
use rustc_span:: Span ;
20
21
@@ -211,43 +212,82 @@ pub fn resolve_interior<'a, 'tcx>(
211
212
212
213
debug ! ( "types in generator {:?}, span = {:?}" , types, body. value. span) ;
213
214
214
- let mut counter = 0 ;
215
+ // We want to deduplicate if the lifetimes are the same modulo some non-informative counter.
216
+ // So, we need to actually do two passes: first by type to anonymize (preserving information
217
+ // required for diagnostics), then a second pass over all captured types to reassign disjoint
218
+ // region indices.
215
219
let mut captured_tys = FxHashSet :: default ( ) ;
216
220
let type_causes: Vec < _ > = types
217
221
. into_iter ( )
218
222
. filter_map ( |mut cause| {
219
- // Erase regions and canonicalize late-bound regions to deduplicate as many types as we
220
- // can.
221
- let ty = fcx. normalize_associated_types_in ( cause. span , cause. ty ) ;
222
- let erased = fcx. tcx . erase_regions ( ty) ;
223
- if captured_tys. insert ( erased) {
224
- // Replace all regions inside the generator interior with late bound regions.
225
- // Note that each region slot in the types gets a new fresh late bound region,
226
- // which means that none of the regions inside relate to any other, even if
227
- // typeck had previously found constraints that would cause them to be related.
228
- let folded = fcx. tcx . fold_regions ( erased, |_, current_depth| {
229
- let br = ty:: BoundRegion {
230
- var : ty:: BoundVar :: from_u32 ( counter) ,
231
- kind : ty:: BrAnon ( counter) ,
232
- } ;
233
- let r = fcx. tcx . mk_region ( ty:: ReLateBound ( current_depth, br) ) ;
234
- counter += 1 ;
235
- r
236
- } ) ;
223
+ // Replace all regions inside the generator interior with late bound regions.
224
+ // Note that each region slot in the types gets a new fresh late bound region,
225
+ // which means that none of the regions inside relate to any other, even if
226
+ // typeck had previously found constraints that would cause them to be related.
237
227
238
- cause. ty = folded;
228
+ let mut counter = 0 ;
229
+ let ty = fcx. normalize_associated_types_in ( cause. span , cause. ty ) ;
230
+ let ty = fcx. tcx . fold_regions ( ty, |region, current_depth| {
231
+ let br = match region. kind ( ) {
232
+ ty:: ReVar ( vid) => {
233
+ let origin = fcx. region_var_origin ( vid) ;
234
+ match origin {
235
+ RegionVariableOrigin :: EarlyBoundRegion ( span, _) => {
236
+ let kind = ty:: BrAnon ( counter, Some ( span) ) ;
237
+ let var = ty:: BoundVar :: from_u32 ( counter) ;
238
+ counter += 1 ;
239
+ ty:: BoundRegion { var, kind }
240
+ }
241
+ _ => {
242
+ let kind = ty:: BrAnon ( counter, None ) ;
243
+ let var = ty:: BoundVar :: from_u32 ( counter) ;
244
+ counter += 1 ;
245
+ ty:: BoundRegion { var, kind }
246
+ }
247
+ }
248
+ }
249
+ _ => {
250
+ let kind = ty:: BrAnon ( counter, None ) ;
251
+ let var = ty:: BoundVar :: from_u32 ( counter) ;
252
+ counter += 1 ;
253
+ ty:: BoundRegion { var, kind }
254
+ }
255
+ } ;
256
+ let r = fcx. tcx . mk_region ( ty:: ReLateBound ( current_depth, br) ) ;
257
+ r
258
+ } ) ;
259
+ if captured_tys. insert ( ty) {
260
+ cause. ty = ty;
239
261
Some ( cause)
240
262
} else {
241
263
None
242
264
}
243
265
} )
244
266
. collect ( ) ;
245
267
268
+ let mut bound_vars: Vec < BoundVariableKind > = vec ! [ ] ;
269
+ let mut counter = 0 ;
270
+ let type_causes = fcx. tcx . fold_regions ( type_causes, |region, current_depth| {
271
+ let br = match region. kind ( ) {
272
+ ty:: ReLateBound ( _, br) => {
273
+ let kind = match br. kind {
274
+ ty:: BrAnon ( _, span) => ty:: BrAnon ( counter, span) ,
275
+ _ => br. kind ,
276
+ } ;
277
+ let var = ty:: BoundVar :: from_usize ( bound_vars. len ( ) ) ;
278
+ bound_vars. push ( ty:: BoundVariableKind :: Region ( kind) ) ;
279
+ counter += 1 ;
280
+ ty:: BoundRegion { var, kind }
281
+ }
282
+ _ => bug ! ( "All regions should have been replaced by ReLateBound" ) ,
283
+ } ;
284
+ let r = fcx. tcx . mk_region ( ty:: ReLateBound ( current_depth, br) ) ;
285
+ r
286
+ } ) ;
287
+
246
288
// Extract type components to build the witness type.
247
289
let type_list = fcx. tcx . mk_type_list ( type_causes. iter ( ) . map ( |cause| cause. ty ) ) ;
248
- let bound_vars = fcx. tcx . mk_bound_variable_kinds (
249
- ( 0 ..counter) . map ( |i| ty:: BoundVariableKind :: Region ( ty:: BrAnon ( i) ) ) ,
250
- ) ;
290
+ let bound_vars = fcx. tcx . mk_bound_variable_kinds ( bound_vars. iter ( ) ) ;
251
291
let witness =
252
292
fcx. tcx . mk_generator_witness ( ty:: Binder :: bind_with_vars ( type_list, bound_vars. clone ( ) ) ) ;
253
293
0 commit comments