@@ -14,10 +14,10 @@ use infer::outlives::free_region_map::FreeRegionRelations;
1414use rustc_data_structures:: fx:: FxHashMap ;
1515use syntax:: ast;
1616use 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 } ;
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,55 +455,184 @@ 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 = 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+ ) ) ;
501466 debug ! (
502467 "infer_anon_definition_from_instantiation: definition_ty={:?}" ,
503468 definition_ty
504469 ) ;
505470
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+
506476 definition_ty
507477 }
508478}
509479
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+
510636struct Instantiator < ' a , ' gcx : ' tcx , ' tcx : ' a > {
511637 infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
512638 parent_def_id : DefId ,
@@ -565,12 +691,13 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
565691 return self . fold_anon_ty ( ty, def_id, substs) ;
566692 }
567693
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+ ) ;
574701 }
575702 }
576703
@@ -590,8 +717,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
590717
591718 debug ! (
592719 "instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})" ,
593- def_id,
594- substs
720+ def_id, substs
595721 ) ;
596722
597723 // Use the same type variable if the exact same TyAnon appears more
@@ -600,8 +726,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
600726 return anon_defn. concrete_ty ;
601727 }
602728 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+ ) ;
605733
606734 let predicates_of = tcx. predicates_of ( def_id) ;
607735 let bounds = predicates_of. instantiate ( tcx, substs) ;
0 commit comments