@@ -669,40 +669,33 @@ fn compute_storage_conflicts(
669
669
storage_conflicts
670
670
}
671
671
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 > (
673
675
tcx : TyCtxt < ' tcx > ,
674
- source : MirSource < ' tcx > ,
676
+ body : & Body < ' tcx > ,
677
+ did : DefId ,
678
+ witness : Ty < ' tcx > ,
675
679
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 > ,
684
681
) {
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
695
682
let allowed_upvars = tcx. erase_regions ( upvars) ;
696
- let allowed = match interior . kind {
683
+ let allowed = match witness . kind {
697
684
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
+ }
699
692
} ;
700
693
701
- let param_env = tcx. param_env ( source . def_id ( ) ) ;
694
+ let param_env = tcx. param_env ( did ) ;
702
695
703
696
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 {
706
699
continue ;
707
700
}
708
701
let decl_ty = tcx. normalize_erasing_regions ( param_env, decl. ty ) ;
@@ -715,10 +708,34 @@ fn compute_layout<'tcx>(
715
708
"Broken MIR: generator contains type {} in MIR, \
716
709
but typeck only knows about {}",
717
710
decl. ty,
718
- interior
711
+ witness ,
719
712
) ;
720
713
}
721
714
}
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) ;
722
739
723
740
// Gather live local types and their indices.
724
741
let mut locals = IndexVec :: < GeneratorSavedLocal , _ > :: new ( ) ;
0 commit comments