@@ -14,10 +14,10 @@ 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
- use ty:: subst:: { Kind , UnpackedKind , Substs } ;
20
+ use ty:: subst:: { Kind , Substs , UnpackedKind } ;
21
21
use util:: nodemap:: DefIdMap ;
22
22
23
23
pub type AnonTypeMap < ' tcx > = DefIdMap < AnonTypeDecl < ' tcx > > ;
@@ -113,10 +113,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
113
113
) -> InferOk < ' tcx , ( T , AnonTypeMap < ' tcx > ) > {
114
114
debug ! (
115
115
"instantiate_anon_types(value={:?}, parent_def_id={:?}, body_id={:?}, param_env={:?})" ,
116
- value,
117
- parent_def_id,
118
- body_id,
119
- param_env,
116
+ value, parent_def_id, body_id, param_env,
120
117
) ;
121
118
let mut instantiator = Instantiator {
122
119
infcx : self ,
@@ -458,55 +455,184 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
458
455
// Convert the type from the function into a type valid outside
459
456
// the function, by replacing invalid regions with 'static,
460
457
// 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
-
458
+ let definition_ty =
459
+ instantiated_ty. fold_with ( & mut ReverseMapper :: new (
460
+ self . tcx ,
461
+ self . is_tainted_by_errors ( ) ,
462
+ def_id,
463
+ map,
464
+ instantiated_ty,
465
+ ) ) ;
501
466
debug ! (
502
467
"infer_anon_definition_from_instantiation: definition_ty={:?}" ,
503
468
definition_ty
504
469
) ;
505
470
471
+ // We can unwrap here because our reverse mapper always
472
+ // produces things with 'gcx lifetime, though the type folder
473
+ // obscures that.
474
+ let definition_ty = gcx. lift ( & definition_ty) . unwrap ( ) ;
475
+
506
476
definition_ty
507
477
}
508
478
}
509
479
480
+ struct ReverseMapper < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
481
+ tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
482
+
483
+ /// If errors have already been reported in this fn, we suppress
484
+ /// our own errors because they are sometimes derivative.
485
+ tainted_by_errors : bool ,
486
+
487
+ anon_type_def_id : DefId ,
488
+ map : FxHashMap < Kind < ' tcx > , Kind < ' gcx > > ,
489
+ map_missing_regions_to_empty : bool ,
490
+
491
+ /// initially `Some`, set to `None` once error has been reported
492
+ hidden_ty : Option < Ty < ' tcx > > ,
493
+ }
494
+
495
+ impl < ' cx , ' gcx , ' tcx > ReverseMapper < ' cx , ' gcx , ' tcx > {
496
+ fn new (
497
+ tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
498
+ tainted_by_errors : bool ,
499
+ anon_type_def_id : DefId ,
500
+ map : FxHashMap < Kind < ' tcx > , Kind < ' gcx > > ,
501
+ hidden_ty : Ty < ' tcx > ,
502
+ ) -> Self {
503
+ Self {
504
+ tcx,
505
+ tainted_by_errors,
506
+ anon_type_def_id,
507
+ map,
508
+ map_missing_regions_to_empty : false ,
509
+ hidden_ty : Some ( hidden_ty) ,
510
+ }
511
+ }
512
+
513
+ fn fold_kind_mapping_missing_regions_to_empty ( & mut self , kind : Kind < ' tcx > ) -> Kind < ' tcx > {
514
+ assert ! ( !self . map_missing_regions_to_empty) ;
515
+ self . map_missing_regions_to_empty = true ;
516
+ let kind = kind. fold_with ( self ) ;
517
+ self . map_missing_regions_to_empty = false ;
518
+ kind
519
+ }
520
+
521
+ fn fold_kind_normally ( & mut self , kind : Kind < ' tcx > ) -> Kind < ' tcx > {
522
+ assert ! ( !self . map_missing_regions_to_empty) ;
523
+ kind. fold_with ( self )
524
+ }
525
+ }
526
+
527
+ impl < ' cx , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for ReverseMapper < ' cx , ' gcx , ' tcx > {
528
+ fn tcx ( & self ) -> TyCtxt < ' _ , ' gcx , ' tcx > {
529
+ self . tcx
530
+ }
531
+
532
+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
533
+ match r {
534
+ // ignore bound regions that appear in the type (e.g., this
535
+ // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
536
+ ty:: ReLateBound ( ..) => return r,
537
+
538
+ // ignore `'static`, as that can appear anywhere
539
+ ty:: ReStatic => return r,
540
+
541
+ _ => { }
542
+ }
543
+
544
+ match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
545
+ Some ( UnpackedKind :: Lifetime ( r1) ) => r1,
546
+ Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
547
+ None => {
548
+ if !self . map_missing_regions_to_empty && !self . tainted_by_errors {
549
+ if let Some ( hidden_ty) = self . hidden_ty . take ( ) {
550
+ let span = self . tcx . def_span ( self . anon_type_def_id ) ;
551
+ let mut err = struct_span_err ! (
552
+ self . tcx. sess,
553
+ span,
554
+ E0909 ,
555
+ "hidden type for `impl Trait` captures lifetime that \
556
+ does not appear in bounds",
557
+ ) ;
558
+
559
+ // Assuming regionck succeeded, then we must
560
+ // be capturing *some* region from the fn
561
+ // header, and hence it must be free, so it's
562
+ // ok to invoke this fn (which doesn't accept
563
+ // all regions, and would ICE if an
564
+ // inappropriate region is given). We check
565
+ // `is_tainted_by_errors` by errors above, so
566
+ // we don't get in here unless regionck
567
+ // succeeded. (Note also that if regionck
568
+ // failed, then the regions we are attempting
569
+ // to map here may well be giving errors
570
+ // *because* the constraints were not
571
+ // satisfiable.)
572
+ self . tcx . note_and_explain_free_region (
573
+ & mut err,
574
+ & format ! ( "hidden type `{}` captures " , hidden_ty) ,
575
+ r,
576
+ ""
577
+ ) ;
578
+
579
+ err. emit ( ) ;
580
+ }
581
+ }
582
+ self . tcx . types . re_empty
583
+ } ,
584
+ }
585
+ }
586
+
587
+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
588
+ match ty. sty {
589
+ ty:: TyClosure ( def_id, substs) => {
590
+ // I am a horrible monster and I pray for death. When
591
+ // we encounter a closure here, it is always a closure
592
+ // from within the function that we are currently
593
+ // type-checking -- one that is now being encapsulated
594
+ // in an existential abstract type. Ideally, we would
595
+ // go through the types/lifetimes that it references
596
+ // and treat them just like we would any other type,
597
+ // which means we would error out if we find any
598
+ // reference to a type/region that is not in the
599
+ // "reverse map".
600
+ //
601
+ // **However,** in the case of closures, there is a
602
+ // somewhat subtle (read: hacky) consideration. The
603
+ // problem is that our closure types currently include
604
+ // all the lifetime parameters declared on the
605
+ // enclosing function, even if they are unused by the
606
+ // closure itself. We can't readily filter them out,
607
+ // so here we replace those values with `'empty`. This
608
+ // can't really make a difference to the rest of the
609
+ // compiler; those regions are ignored for the
610
+ // outlives relation, and hence don't affect trait
611
+ // selection or auto traits, and they are erased
612
+ // during trans.
613
+
614
+ let generics = self . tcx . generics_of ( def_id) ;
615
+ let parent_len = generics. parent_count ( ) ;
616
+ let substs = self . tcx . mk_substs ( substs. substs . iter ( ) . enumerate ( ) . map (
617
+ |( index, & kind) | {
618
+ if index < parent_len {
619
+ // Accommodate missing regions in the parent kinds...
620
+ self . fold_kind_mapping_missing_regions_to_empty ( kind)
621
+ } else {
622
+ // ...but not elsewhere.
623
+ self . fold_kind_normally ( kind)
624
+ }
625
+ } ,
626
+ ) ) ;
627
+
628
+ self . tcx . mk_closure ( def_id, ty:: ClosureSubsts { substs } )
629
+ }
630
+
631
+ _ => ty. super_fold_with ( self ) ,
632
+ }
633
+ }
634
+ }
635
+
510
636
struct Instantiator < ' a , ' gcx : ' tcx , ' tcx : ' a > {
511
637
infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
512
638
parent_def_id : DefId ,
@@ -565,12 +691,13 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
565
691
return self . fold_anon_ty ( ty, def_id, substs) ;
566
692
}
567
693
568
- debug ! ( "instantiate_anon_types_in_map: \
569
- encountered anon with wrong parent \
570
- def_id={:?} \
571
- anon_parent_def_id={:?}",
572
- def_id,
573
- anon_parent_def_id) ;
694
+ debug ! (
695
+ "instantiate_anon_types_in_map: \
696
+ encountered anon with wrong parent \
697
+ def_id={:?} \
698
+ anon_parent_def_id={:?}",
699
+ def_id, anon_parent_def_id
700
+ ) ;
574
701
}
575
702
}
576
703
@@ -590,8 +717,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
590
717
591
718
debug ! (
592
719
"instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})" ,
593
- def_id,
594
- substs
720
+ def_id, substs
595
721
) ;
596
722
597
723
// Use the same type variable if the exact same TyAnon appears more
@@ -600,8 +726,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
600
726
return anon_defn. concrete_ty ;
601
727
}
602
728
let span = tcx. def_span ( def_id) ;
603
- let ty_var = infcx. next_ty_var ( ty:: UniverseIndex :: ROOT ,
604
- TypeVariableOrigin :: TypeInference ( span) ) ;
729
+ let ty_var = infcx. next_ty_var (
730
+ ty:: UniverseIndex :: ROOT ,
731
+ TypeVariableOrigin :: TypeInference ( span) ,
732
+ ) ;
605
733
606
734
let predicates_of = tcx. predicates_of ( def_id) ;
607
735
let bounds = predicates_of. instantiate ( tcx, substs) ;
0 commit comments