@@ -557,6 +557,31 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
557557 state. kill_all ( definitely_conflicting_borrows) ;
558558 }
559559
560+ /// Kill pinned borrows whose borrowed place's local matches `local`.
561+ /// This is called in the early phase when the borrowed place's storage dies,
562+ /// to prevent spurious E0716 errors.
563+ fn kill_pinned_borrows_on_borrowed_local (
564+ & self ,
565+ state : & mut <Self as Analysis < ' tcx > >:: Domain ,
566+ local : mir:: Local ,
567+ ) {
568+ debug ! ( "kill_pinned_borrows_on_borrowed_local: local={:?}" , local) ;
569+
570+ let to_kill: Vec < _ > = self
571+ . borrow_set
572+ . iter_enumerated ( )
573+ . filter_map ( |( idx, data) | {
574+ if data. is_pinned ( ) && data. borrowed_place . local == local {
575+ Some ( idx)
576+ } else {
577+ None
578+ }
579+ } )
580+ . collect ( ) ;
581+
582+ state. kill_all ( to_kill. into_iter ( ) ) ;
583+ }
584+
560585 /// Kill pinned borrows whose Pin result local matches `local`.
561586 /// This is called when the Pin value goes out of scope (StorageDead).
562587 fn kill_pinned_borrows_on_local (
@@ -569,9 +594,11 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
569594 let to_kill: Vec < _ > = self
570595 . borrow_set
571596 . iter_enumerated ( )
572- . filter_map ( |( idx, data) | {
573- if data. pin_target_local ( ) == Some ( local) { Some ( idx) } else { None }
574- } )
597+ . filter_map (
598+ |( idx, data) | {
599+ if data. pin_target_local ( ) == Some ( local) { Some ( idx) } else { None }
600+ } ,
601+ )
575602 . collect ( ) ;
576603
577604 state. kill_all ( to_kill. into_iter ( ) ) ;
@@ -596,8 +623,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
596623
597624 if place. projection . is_empty ( ) {
598625 // Only kill pinned borrows, not regular ones
599- let pinned_borrows = other_borrows_of_local
600- . filter ( |& i| self . borrow_set [ i] . is_pinned ( ) ) ;
626+ let pinned_borrows = other_borrows_of_local. filter ( |& i| self . borrow_set [ i] . is_pinned ( ) ) ;
601627 state. kill_all ( pinned_borrows) ;
602628 return ;
603629 }
@@ -649,11 +675,23 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
649675 ) {
650676 self . kill_loans_out_of_scope_at_location ( state, location) ;
651677
652- // For pinned borrows whose lifetime is extended beyond NLL scope,
653- // kill them early when the pinned place is reassigned. This allows
654- // the reassignment to proceed without conflicting with the borrow.
655- if let mir:: StatementKind :: Assign ( box ( lhs, _) ) = & statement. kind {
656- self . kill_pinned_borrows_on_reassignment ( state, * lhs) ;
678+ match & statement. kind {
679+ // For pinned borrows whose lifetime is extended beyond NLL scope,
680+ // kill them early when the pinned place is reassigned. This allows
681+ // the reassignment to proceed without conflicting with the borrow.
682+ mir:: StatementKind :: Assign ( box ( lhs, _) ) => {
683+ self . kill_pinned_borrows_on_reassignment ( state, * lhs) ;
684+ }
685+ // Kill pinned borrows in the early phase when the borrowed place's
686+ // local has StorageDead. This must happen before the visitor's
687+ // StorageDead check (which runs after early effects) to avoid
688+ // spurious E0716 errors for temporaries whose storage dies before
689+ // the Pin result local.
690+ mir:: StatementKind :: StorageDead ( local) => {
691+ self . kill_pinned_borrows_on_local ( state, * local) ;
692+ self . kill_pinned_borrows_on_borrowed_local ( state, * local) ;
693+ }
694+ _ => { }
657695 }
658696 }
659697
@@ -736,29 +774,16 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
736774}
737775
738776impl < ' a , ' tcx > Pins < ' a , ' tcx > {
739- pub ( crate ) fn new (
740- tcx : TyCtxt < ' tcx > ,
741- body : & ' a Body < ' tcx > ,
742- pin_set : & ' a PinSet < ' tcx > ,
743- ) -> Self {
777+ pub ( crate ) fn new ( tcx : TyCtxt < ' tcx > , body : & ' a Body < ' tcx > , pin_set : & ' a PinSet < ' tcx > ) -> Self {
744778 Pins { tcx, body, pin_set }
745779 }
746780
747781 /// Kill any pins whose original pinned place conflicts with `place`.
748- fn kill_pins_on_place (
749- & self ,
750- state : & mut <Self as Analysis < ' tcx > >:: Domain ,
751- place : Place < ' tcx > ,
752- ) {
782+ fn kill_pins_on_place ( & self , state : & mut <Self as Analysis < ' tcx > >:: Domain , place : Place < ' tcx > ) {
753783 debug ! ( "kill_pins_on_place: place={:?}" , place) ;
754784
755- let other_pins_of_local = self
756- . pin_set
757- . local_map
758- . get ( & place. local )
759- . into_iter ( )
760- . flat_map ( |ps| ps. iter ( ) )
761- . copied ( ) ;
785+ let other_pins_of_local =
786+ self . pin_set . local_map . get ( & place. local ) . into_iter ( ) . flat_map ( |ps| ps. iter ( ) ) . copied ( ) ;
762787
763788 // If the place is a local with no projections, all pins of this
764789 // local must be killed. This is purely an optimization so we don't have to call
@@ -794,13 +819,8 @@ impl<'a, 'tcx> Pins<'a, 'tcx> {
794819 ) {
795820 debug ! ( "kill_pins_by_pin_local: local={:?}" , local) ;
796821
797- let pins_of_local = self
798- . pin_set
799- . pin_local_map
800- . get ( & local)
801- . into_iter ( )
802- . flat_map ( |ps| ps. iter ( ) )
803- . copied ( ) ;
822+ let pins_of_local =
823+ self . pin_set . pin_local_map . get ( & local) . into_iter ( ) . flat_map ( |ps| ps. iter ( ) ) . copied ( ) ;
804824
805825 state. kill_all ( pins_of_local) ;
806826 }
0 commit comments