@@ -17,7 +17,7 @@ use traits::{self, PredicateObligation};
1717use ty:: { self , Ty , TyCtxt } ;
1818use ty:: fold:: { BottomUpFolder , TypeFoldable , TypeFolder } ;
1919use ty:: outlives:: Component ;
20- use ty:: subst:: { Kind , UnpackedKind , Substs } ;
20+ use ty:: subst:: { Kind , Substs , UnpackedKind } ;
2121use util:: nodemap:: DefIdMap ;
2222
2323pub type AnonTypeMap < ' tcx > = DefIdMap < AnonTypeDecl < ' tcx > > ;
@@ -113,10 +113,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
113113 ) -> InferOk < ' tcx , ( T , AnonTypeMap < ' tcx > ) > {
114114 debug ! (
115115 "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,
120117 ) ;
121118 let mut instantiator = Instantiator {
122119 infcx : self ,
@@ -458,7 +455,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
458455 // Convert the type from the function into a type valid outside
459456 // the function, by replacing invalid regions with 'static,
460457 // 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+ ) ) ;
462466 debug ! (
463467 "infer_anon_definition_from_instantiation: definition_ty={:?}" ,
464468 definition_ty
@@ -475,7 +479,49 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
475479
476480struct ReverseMapper < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
477481 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+ }
479525}
480526
481527impl < ' 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>
484530 }
485531
486532 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+ _ => { }
491542 }
492543
493544 match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
494545 Some ( UnpackedKind :: Lifetime ( r1) ) => r1,
495546 Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
496547 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".
501600 //
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,
507607 // so here we replace those values with `'empty`. This
508608 // 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 } )
513629 }
630+
631+ _ => ty. super_fold_with ( self ) ,
514632 }
515633 }
516634}
@@ -573,12 +691,13 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
573691 return self . fold_anon_ty ( ty, def_id, substs) ;
574692 }
575693
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+ ) ;
582701 }
583702 }
584703
@@ -598,8 +717,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
598717
599718 debug ! (
600719 "instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})" ,
601- def_id,
602- substs
720+ def_id, substs
603721 ) ;
604722
605723 // Use the same type variable if the exact same TyAnon appears more
@@ -608,8 +726,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
608726 return anon_defn. concrete_ty ;
609727 }
610728 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+ ) ;
613733
614734 let predicates_of = tcx. predicates_of ( def_id) ;
615735 let bounds = predicates_of. instantiate ( tcx, substs) ;
0 commit comments