@@ -15,9 +15,11 @@ use rustc_hir::intravisit::{self, Visitor};
15
15
use rustc_hir:: { Arm , Expr , ExprKind , Guard , HirId , Pat , PatKind } ;
16
16
use rustc_infer:: infer:: RegionVariableOrigin ;
17
17
use rustc_middle:: middle:: region:: { self , Scope , ScopeData , YieldData } ;
18
+ use rustc_middle:: ty:: fold:: FnMutDelegate ;
18
19
use rustc_middle:: ty:: { self , BoundVariableKind , RvalueScopes , Ty , TyCtxt , TypeVisitable } ;
19
20
use rustc_span:: symbol:: sym;
20
21
use rustc_span:: Span ;
22
+ use smallvec:: { smallvec, SmallVec } ;
21
23
22
24
mod drop_ranges;
23
25
@@ -226,32 +228,37 @@ pub fn resolve_interior<'a, 'tcx>(
226
228
// typeck had previously found constraints that would cause them to be related.
227
229
228
230
let mut counter = 0 ;
231
+ let mut mk_bound_region = |span| {
232
+ let kind = ty:: BrAnon ( counter, span) ;
233
+ let var = ty:: BoundVar :: from_u32 ( counter) ;
234
+ counter += 1 ;
235
+ ty:: BoundRegion { var, kind }
236
+ } ;
229
237
let ty = fcx. normalize_associated_types_in ( cause. span , cause. ty ) ;
230
238
let ty = fcx. tcx . fold_regions ( ty, |region, current_depth| {
231
239
let br = match region. kind ( ) {
232
240
ty:: ReVar ( vid) => {
233
241
let origin = fcx. region_var_origin ( vid) ;
234
242
match origin {
235
243
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 }
244
+ mk_bound_region ( Some ( span) )
246
245
}
246
+ _ => mk_bound_region ( None ) ,
247
247
}
248
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 }
249
+ // FIXME: these should use `BrNamed`
250
+ ty:: ReEarlyBound ( region) => {
251
+ mk_bound_region ( Some ( fcx. tcx . def_span ( region. def_id ) ) )
254
252
}
253
+ ty:: ReLateBound ( _, ty:: BoundRegion { kind, .. } )
254
+ | ty:: ReFree ( ty:: FreeRegion { bound_region : kind, .. } ) => match kind {
255
+ ty:: BoundRegionKind :: BrAnon ( _, span) => mk_bound_region ( span) ,
256
+ ty:: BoundRegionKind :: BrNamed ( def_id, _) => {
257
+ mk_bound_region ( Some ( fcx. tcx . def_span ( def_id) ) )
258
+ }
259
+ ty:: BoundRegionKind :: BrEnv => mk_bound_region ( None ) ,
260
+ } ,
261
+ _ => mk_bound_region ( None ) ,
255
262
} ;
256
263
let r = fcx. tcx . mk_region ( ty:: ReLateBound ( current_depth, br) ) ;
257
264
r
@@ -265,25 +272,34 @@ pub fn resolve_interior<'a, 'tcx>(
265
272
} )
266
273
. collect ( ) ;
267
274
268
- let mut bound_vars: Vec < BoundVariableKind > = vec ! [ ] ;
275
+ let mut bound_vars: SmallVec < [ BoundVariableKind ; 4 ] > = smallvec ! [ ] ;
269
276
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
- } ) ;
277
+ // Optimization: If there is only one captured type, then we don't actually
278
+ // need to fold and reindex (since the first type doesn't change).
279
+ let type_causes = if captured_tys. len ( ) > 0 {
280
+ // Optimization: Use `replace_escaping_bound_vars_uncached` instead of
281
+ // `fold_regions`, since we only have late bound regions, and it skips
282
+ // types without bound regions.
283
+ fcx. tcx . replace_escaping_bound_vars_uncached (
284
+ type_causes,
285
+ FnMutDelegate {
286
+ regions : & mut |br| {
287
+ let kind = match br. kind {
288
+ ty:: BrAnon ( _, span) => ty:: BrAnon ( counter, span) ,
289
+ _ => br. kind ,
290
+ } ;
291
+ let var = ty:: BoundVar :: from_usize ( bound_vars. len ( ) ) ;
292
+ bound_vars. push ( ty:: BoundVariableKind :: Region ( kind) ) ;
293
+ counter += 1 ;
294
+ fcx. tcx . mk_region ( ty:: ReLateBound ( ty:: INNERMOST , ty:: BoundRegion { var, kind } ) )
295
+ } ,
296
+ types : & mut |b| bug ! ( "unexpected bound ty in binder: {b:?}" ) ,
297
+ consts : & mut |b, ty| bug ! ( "unexpected bound ct in binder: {b:?} {ty}" ) ,
298
+ } ,
299
+ )
300
+ } else {
301
+ type_causes
302
+ } ;
287
303
288
304
// Extract type components to build the witness type.
289
305
let type_list = fcx. tcx . mk_type_list ( type_causes. iter ( ) . map ( |cause| cause. ty ) ) ;
0 commit comments