@@ -14,8 +14,8 @@ use infer::outlives::free_region_map::FreeRegionRelations;
14
14
use rustc_data_structures:: fx:: FxHashMap ;
15
15
use syntax:: ast;
16
16
use traits:: { self , PredicateObligation } ;
17
- use ty:: { self , Ty } ;
18
- use ty:: fold:: { BottomUpFolder , TypeFoldable } ;
17
+ use ty:: { self , Ty , TyCtxt } ;
18
+ use ty:: fold:: { BottomUpFolder , TypeFoldable , TypeFolder } ;
19
19
use ty:: outlives:: Component ;
20
20
use ty:: subst:: { Kind , UnpackedKind , Substs } ;
21
21
use util:: nodemap:: DefIdMap ;
@@ -458,55 +458,63 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
458
458
// Convert the type from the function into a type valid outside
459
459
// the function, by replacing invalid regions with 'static,
460
460
// after producing an error for each of them.
461
- let definition_ty = gcx. fold_regions ( & instantiated_ty, & mut false , |r, _| {
462
- match * r {
463
- // 'static and early-bound regions are valid.
464
- ty:: ReStatic | ty:: ReEmpty => r,
465
-
466
- // All other regions, we map them appropriately to their adjusted
467
- // indices, erroring if we find any lifetimes that were not mapped
468
- // into the new set.
469
- _ => if let Some ( UnpackedKind :: Lifetime ( r1) ) = map. get ( & r. into ( ) )
470
- . map ( |k| k. unpack ( ) ) {
471
- r1
472
- } else {
473
- // No mapping was found. This means that
474
- // it is either a disallowed lifetime,
475
- // which will be caught by regionck, or it
476
- // is a region in a non-upvar closure
477
- // generic, which is explicitly
478
- // allowed. If that surprises you, read
479
- // on.
480
- //
481
- // The case of closure is a somewhat
482
- // subtle (read: hacky) consideration. The
483
- // problem is that our closure types
484
- // currently include all the lifetime
485
- // parameters declared on the enclosing
486
- // function, even if they are unused by
487
- // the closure itself. We can't readily
488
- // filter them out, so here we replace
489
- // those values with `'empty`. This can't
490
- // really make a difference to the rest of
491
- // the compiler; those regions are ignored
492
- // for the outlives relation, and hence
493
- // don't affect trait selection or auto
494
- // traits, and they are erased during
495
- // trans.
496
- gcx. types . re_empty
497
- } ,
498
- }
499
- } ) ;
500
-
461
+ let definition_ty = instantiated_ty. fold_with ( & mut ReverseMapper { tcx : self . tcx , map } ) ;
501
462
debug ! (
502
463
"infer_anon_definition_from_instantiation: definition_ty={:?}" ,
503
464
definition_ty
504
465
) ;
505
466
467
+ // We can unwrap here because our reverse mapper always
468
+ // produces things with 'gcx lifetime, though the type folder
469
+ // obscures that.
470
+ let definition_ty = gcx. lift ( & definition_ty) . unwrap ( ) ;
471
+
506
472
definition_ty
507
473
}
508
474
}
509
475
476
+ struct ReverseMapper < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
477
+ tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
478
+ map : FxHashMap < Kind < ' tcx > , Kind < ' gcx > >
479
+ }
480
+
481
+ impl < ' cx , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for ReverseMapper < ' cx , ' gcx , ' tcx > {
482
+ fn tcx ( & self ) -> TyCtxt < ' _ , ' gcx , ' tcx > {
483
+ self . tcx
484
+ }
485
+
486
+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
487
+ // ignore bound regions that appear in the type (e.g., this
488
+ // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
489
+ if let ty:: ReLateBound ( ..) = * r {
490
+ return r;
491
+ }
492
+
493
+ match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
494
+ Some ( UnpackedKind :: Lifetime ( r1) ) => r1,
495
+ Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
496
+ None => {
497
+ // No mapping was found. This means that it is either a
498
+ // disallowed lifetime, which will be caught by regionck,
499
+ // or it is a region in a non-upvar closure generic, which
500
+ // is explicitly allowed. If that surprises you, read on.
501
+ //
502
+ // The case of closure is a somewhat subtle (read: hacky)
503
+ // consideration. The problem is that our closure types
504
+ // currently include all the lifetime parameters declared
505
+ // on the enclosing function, even if they are unused by
506
+ // the closure itself. We can't readily filter them out,
507
+ // so here we replace those values with `'empty`. This
508
+ // can't really make a difference to the rest of the
509
+ // compiler; those regions are ignored for the outlives
510
+ // relation, and hence don't affect trait selection or
511
+ // auto traits, and they are erased during trans.
512
+ self . tcx . types . re_empty
513
+ }
514
+ }
515
+ }
516
+ }
517
+
510
518
struct Instantiator < ' a , ' gcx : ' tcx , ' tcx : ' a > {
511
519
infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
512
520
parent_def_id : DefId ,
0 commit comments