@@ -639,6 +639,15 @@ struct LivenessInfo {
639
639
/// Parallel vec to the above with SourceInfo for each yield terminator.
640
640
source_info_at_suspension_points : Vec < SourceInfo > ,
641
641
642
+ /// Coroutine saved locals that are borrowed across a suspension point.
643
+ /// This corresponds to locals that are "wrapped" with `UnsafePinned`.
644
+ ///
645
+ /// Note that movable coroutines do not allow borrowing locals across
646
+ /// suspension points and thus will always have this set empty.
647
+ ///
648
+ /// For more information, see [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
649
+ saved_locals_borrowed_across_suspension_points : DenseBitSet < CoroutineSavedLocal > ,
650
+
642
651
/// For every saved local, the set of other saved locals that are
643
652
/// storage-live at the same time as this local. We cannot overlap locals in
644
653
/// the layout which have conflicting storage.
@@ -690,6 +699,8 @@ fn locals_live_across_suspend_points<'tcx>(
690
699
let mut live_locals_at_suspension_points = Vec :: new ( ) ;
691
700
let mut source_info_at_suspension_points = Vec :: new ( ) ;
692
701
let mut live_locals_at_any_suspension_point = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
702
+ let mut locals_borrowed_across_any_suspension_point =
703
+ DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
693
704
694
705
for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
695
706
if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -711,6 +722,7 @@ fn locals_live_across_suspend_points<'tcx>(
711
722
// of the local, which happens using the `intersect` operation below.
712
723
borrowed_locals_cursor. seek_before_primary_effect ( loc) ;
713
724
live_locals. union ( borrowed_locals_cursor. get ( ) ) ;
725
+ locals_borrowed_across_any_suspension_point. union ( borrowed_locals_cursor. get ( ) ) ;
714
726
}
715
727
716
728
// Store the storage liveness for later use so we can restore the state
@@ -726,6 +738,7 @@ fn locals_live_across_suspend_points<'tcx>(
726
738
727
739
// The coroutine argument is ignored.
728
740
live_locals. remove ( SELF_ARG ) ;
741
+ locals_borrowed_across_any_suspension_point. remove ( SELF_ARG ) ;
729
742
730
743
debug ! ( "loc = {:?}, live_locals = {:?}" , loc, live_locals) ;
731
744
@@ -741,13 +754,18 @@ fn locals_live_across_suspend_points<'tcx>(
741
754
debug ! ( "live_locals_anywhere = {:?}" , live_locals_at_any_suspension_point) ;
742
755
let saved_locals = CoroutineSavedLocals ( live_locals_at_any_suspension_point) ;
743
756
757
+ debug ! ( "borrowed_locals = {:?}" , locals_borrowed_across_any_suspension_point) ;
758
+
744
759
// Renumber our liveness_map bitsets to include only the locals we are
745
760
// saving.
746
761
let live_locals_at_suspension_points = live_locals_at_suspension_points
747
762
. iter ( )
748
763
. map ( |live_here| saved_locals. renumber_bitset ( live_here) )
749
764
. collect ( ) ;
750
765
766
+ let saved_locals_borrowed_across_suspension_points =
767
+ saved_locals. renumber_bitset ( & locals_borrowed_across_any_suspension_point) ;
768
+
751
769
let storage_conflicts = compute_storage_conflicts (
752
770
body,
753
771
& saved_locals,
@@ -759,6 +777,7 @@ fn locals_live_across_suspend_points<'tcx>(
759
777
saved_locals,
760
778
live_locals_at_suspension_points,
761
779
source_info_at_suspension_points,
780
+ saved_locals_borrowed_across_suspension_points,
762
781
storage_conflicts,
763
782
storage_liveness : storage_liveness_map,
764
783
}
@@ -931,6 +950,7 @@ fn compute_layout<'tcx>(
931
950
saved_locals,
932
951
live_locals_at_suspension_points,
933
952
source_info_at_suspension_points,
953
+ saved_locals_borrowed_across_suspension_points,
934
954
storage_conflicts,
935
955
storage_liveness,
936
956
} = liveness;
@@ -960,8 +980,14 @@ fn compute_layout<'tcx>(
960
980
ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
961
981
_ => false ,
962
982
} ;
963
- let decl =
964
- CoroutineSavedTy { ty : decl. ty , source_info : decl. source_info , ignore_for_traits } ;
983
+ let pinned = saved_locals_borrowed_across_suspension_points. contains ( saved_local) ;
984
+
985
+ let decl = CoroutineSavedTy {
986
+ ty : decl. ty ,
987
+ source_info : decl. source_info ,
988
+ ignore_for_traits,
989
+ pinned,
990
+ } ;
965
991
debug ! ( ?decl) ;
966
992
967
993
tys. push ( decl) ;
0 commit comments