@@ -17,7 +17,7 @@ use traits::{self, PredicateObligation};
17
17
use ty:: { self , Ty , TyCtxt } ;
18
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,7 +455,14 @@ 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 = instantiated_ty. fold_with ( & mut ReverseMapper { tcx : self . tcx , map } ) ;
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
+ ) ) ;
462
466
debug ! (
463
467
"infer_anon_definition_from_instantiation: definition_ty={:?}" ,
464
468
definition_ty
@@ -475,7 +479,49 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
475
479
476
480
struct ReverseMapper < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
477
481
tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
478
- map : FxHashMap < Kind < ' tcx > , Kind < ' gcx > >
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
+ }
479
525
}
480
526
481
527
impl < ' cx , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for ReverseMapper < ' cx , ' gcx , ' tcx > {
@@ -484,33 +530,105 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>
484
530
}
485
531
486
532
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;
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
+ _ => { }
491
542
}
492
543
493
544
match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
494
545
Some ( UnpackedKind :: Lifetime ( r1) ) => r1,
495
546
Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
496
547
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.
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".
501
600
//
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,
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,
507
607
// so here we replace those values with `'empty`. This
508
608
// 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
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 } )
513
629
}
630
+
631
+ _ => ty. super_fold_with ( self ) ,
514
632
}
515
633
}
516
634
}
@@ -573,12 +691,13 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
573
691
return self . fold_anon_ty ( ty, def_id, substs) ;
574
692
}
575
693
576
- debug ! ( "instantiate_anon_types_in_map: \
577
- encountered anon with wrong parent \
578
- def_id={:?} \
579
- anon_parent_def_id={:?}",
580
- def_id,
581
- 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
+ ) ;
582
701
}
583
702
}
584
703
@@ -598,8 +717,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
598
717
599
718
debug ! (
600
719
"instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})" ,
601
- def_id,
602
- substs
720
+ def_id, substs
603
721
) ;
604
722
605
723
// Use the same type variable if the exact same TyAnon appears more
@@ -608,8 +726,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
608
726
return anon_defn. concrete_ty ;
609
727
}
610
728
let span = tcx. def_span ( def_id) ;
611
- let ty_var = infcx. next_ty_var ( ty:: UniverseIndex :: ROOT ,
612
- TypeVariableOrigin :: TypeInference ( span) ) ;
729
+ let ty_var = infcx. next_ty_var (
730
+ ty:: UniverseIndex :: ROOT ,
731
+ TypeVariableOrigin :: TypeInference ( span) ,
732
+ ) ;
613
733
614
734
let predicates_of = tcx. predicates_of ( def_id) ;
615
735
let bounds = predicates_of. instantiate ( tcx, substs) ;
0 commit comments