@@ -639,6 +639,15 @@ struct LivenessInfo {
639639 /// Parallel vec to the above with SourceInfo for each yield terminator.
640640 source_info_at_suspension_points : Vec < SourceInfo > ,
641641
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+
642651 /// For every saved local, the set of other saved locals that are
643652 /// storage-live at the same time as this local. We cannot overlap locals in
644653 /// the layout which have conflicting storage.
@@ -690,6 +699,8 @@ fn locals_live_across_suspend_points<'tcx>(
690699 let mut live_locals_at_suspension_points = Vec :: new ( ) ;
691700 let mut source_info_at_suspension_points = Vec :: new ( ) ;
692701 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 ( ) ) ;
693704
694705 for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
695706 if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -711,6 +722,7 @@ fn locals_live_across_suspend_points<'tcx>(
711722 // of the local, which happens using the `intersect` operation below.
712723 borrowed_locals_cursor. seek_before_primary_effect ( loc) ;
713724 live_locals. union ( borrowed_locals_cursor. get ( ) ) ;
725+ locals_borrowed_across_any_suspension_point. union ( borrowed_locals_cursor. get ( ) ) ;
714726 }
715727
716728 // Store the storage liveness for later use so we can restore the state
@@ -726,6 +738,7 @@ fn locals_live_across_suspend_points<'tcx>(
726738
727739 // The coroutine argument is ignored.
728740 live_locals. remove ( SELF_ARG ) ;
741+ locals_borrowed_across_any_suspension_point. remove ( SELF_ARG ) ;
729742
730743 debug ! ( "loc = {:?}, live_locals = {:?}" , loc, live_locals) ;
731744
@@ -741,13 +754,18 @@ fn locals_live_across_suspend_points<'tcx>(
741754 debug ! ( "live_locals_anywhere = {:?}" , live_locals_at_any_suspension_point) ;
742755 let saved_locals = CoroutineSavedLocals ( live_locals_at_any_suspension_point) ;
743756
757+ debug ! ( "borrowed_locals = {:?}" , locals_borrowed_across_any_suspension_point) ;
758+
744759 // Renumber our liveness_map bitsets to include only the locals we are
745760 // saving.
746761 let live_locals_at_suspension_points = live_locals_at_suspension_points
747762 . iter ( )
748763 . map ( |live_here| saved_locals. renumber_bitset ( live_here) )
749764 . collect ( ) ;
750765
766+ let saved_locals_borrowed_across_suspension_points =
767+ saved_locals. renumber_bitset ( & locals_borrowed_across_any_suspension_point) ;
768+
751769 let storage_conflicts = compute_storage_conflicts (
752770 body,
753771 & saved_locals,
@@ -759,6 +777,7 @@ fn locals_live_across_suspend_points<'tcx>(
759777 saved_locals,
760778 live_locals_at_suspension_points,
761779 source_info_at_suspension_points,
780+ saved_locals_borrowed_across_suspension_points,
762781 storage_conflicts,
763782 storage_liveness : storage_liveness_map,
764783 }
@@ -931,6 +950,7 @@ fn compute_layout<'tcx>(
931950 saved_locals,
932951 live_locals_at_suspension_points,
933952 source_info_at_suspension_points,
953+ saved_locals_borrowed_across_suspension_points,
934954 storage_conflicts,
935955 storage_liveness,
936956 } = liveness;
@@ -960,8 +980,14 @@ fn compute_layout<'tcx>(
960980 ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
961981 _ => false ,
962982 } ;
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+ } ;
965991 debug ! ( ?decl) ;
966992
967993 tys. push ( decl) ;
0 commit comments