@@ -669,40 +669,33 @@ fn compute_storage_conflicts(
669669 storage_conflicts
670670}
671671
672- fn compute_layout < ' tcx > (
672+ /// Validates the typeck view of the generator against the actual set of types retained between
673+ /// yield points.
674+ fn sanitize_witness < ' tcx > (
673675 tcx : TyCtxt < ' tcx > ,
674- source : MirSource < ' tcx > ,
676+ body : & Body < ' tcx > ,
677+ did : DefId ,
678+ witness : Ty < ' tcx > ,
675679 upvars : & Vec < Ty < ' tcx > > ,
676- interior : Ty < ' tcx > ,
677- always_live_locals : & storage:: AlwaysLiveLocals ,
678- movable : bool ,
679- body : & mut Body < ' tcx > ,
680- ) -> (
681- FxHashMap < Local , ( Ty < ' tcx > , VariantIdx , usize ) > ,
682- GeneratorLayout < ' tcx > ,
683- IndexVec < BasicBlock , Option < BitSet < Local > > > ,
680+ retained : & BitSet < Local > ,
684681) {
685- // Use a liveness analysis to compute locals which are live across a suspension point
686- let LivenessInfo {
687- live_locals,
688- live_locals_at_suspension_points,
689- storage_conflicts,
690- storage_liveness,
691- } = locals_live_across_suspend_points ( tcx, body, source, always_live_locals, movable) ;
692-
693- // Erase regions from the types passed in from typeck so we can compare them with
694- // MIR types
695682 let allowed_upvars = tcx. erase_regions ( upvars) ;
696- let allowed = match interior . kind {
683+ let allowed = match witness . kind {
697684 ty:: GeneratorWitness ( s) => tcx. erase_late_bound_regions ( & s) ,
698- _ => bug ! ( ) ,
685+ _ => {
686+ tcx. sess . delay_span_bug (
687+ body. span ,
688+ & format ! ( "unexpected generator witness type {:?}" , witness. kind) ,
689+ ) ;
690+ return ;
691+ }
699692 } ;
700693
701- let param_env = tcx. param_env ( source . def_id ( ) ) ;
694+ let param_env = tcx. param_env ( did ) ;
702695
703696 for ( local, decl) in body. local_decls . iter_enumerated ( ) {
704- // Ignore locals which are internal or not live
705- if !live_locals . contains ( local) || decl. internal {
697+ // Ignore locals which are internal or not retained between yields.
698+ if !retained . contains ( local) || decl. internal {
706699 continue ;
707700 }
708701 let decl_ty = tcx. normalize_erasing_regions ( param_env, decl. ty ) ;
@@ -715,10 +708,34 @@ fn compute_layout<'tcx>(
715708 "Broken MIR: generator contains type {} in MIR, \
716709 but typeck only knows about {}",
717710 decl. ty,
718- interior
711+ witness ,
719712 ) ;
720713 }
721714 }
715+ }
716+
717+ fn compute_layout < ' tcx > (
718+ tcx : TyCtxt < ' tcx > ,
719+ source : MirSource < ' tcx > ,
720+ upvars : & Vec < Ty < ' tcx > > ,
721+ interior : Ty < ' tcx > ,
722+ always_live_locals : & storage:: AlwaysLiveLocals ,
723+ movable : bool ,
724+ body : & mut Body < ' tcx > ,
725+ ) -> (
726+ FxHashMap < Local , ( Ty < ' tcx > , VariantIdx , usize ) > ,
727+ GeneratorLayout < ' tcx > ,
728+ IndexVec < BasicBlock , Option < BitSet < Local > > > ,
729+ ) {
730+ // Use a liveness analysis to compute locals which are live across a suspension point
731+ let LivenessInfo {
732+ live_locals,
733+ live_locals_at_suspension_points,
734+ storage_conflicts,
735+ storage_liveness,
736+ } = locals_live_across_suspend_points ( tcx, body, source, always_live_locals, movable) ;
737+
738+ sanitize_witness ( tcx, body, source. def_id ( ) , interior, upvars, & live_locals) ;
722739
723740 // Gather live local types and their indices.
724741 let mut locals = IndexVec :: < GeneratorSavedLocal , _ > :: new ( ) ;
0 commit comments