@@ -590,8 +590,12 @@ fn save_as_intervals<'tcx>(
590590 twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
591591 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: After ) ) ;
592592 append_at ( & mut values, & state, twostep) ;
593- // Ensure we have a non-zero live range even for dead stores. This is done by marking
594- // all the written-to locals as live in the second half of the statement.
593+ // Like terminators, ensure we have a non-zero live range even for dead stores.
594+ // Some rvalues interleave reads and writes, for instance `Rvalue::Aggregate`, see
595+ // https://github.com/rust-lang/rust/issues/146383. By precaution, treat statements
596+ // as behaving so by default.
597+ // We make an exception for simple assignments `_a.stuff = {copy|move} _b.stuff`,
598+ // as marking `_b` live here would prevent unification.
595599 let is_simple_assignment =
596600 matches ! ( stmt. kind, StatementKind :: Assign ( box ( _, Rvalue :: Use ( _) ) ) ) ;
597601 VisitPlacesWith ( |place : Place < ' tcx > , ctxt| {
@@ -600,10 +604,12 @@ fn save_as_intervals<'tcx>(
600604 DefUse :: Def | DefUse :: PartialWrite => {
601605 values. insert ( relevant, twostep) ;
602606 }
603- DefUse :: Use if !is_simple_assignment => {
604- values. insert ( relevant, twostep) ;
607+ DefUse :: Use => {
608+ if !is_simple_assignment {
609+ values. insert ( relevant, twostep) ;
610+ }
605611 }
606- DefUse :: Use | DefUse :: NonUse => { }
612+ DefUse :: NonUse => { }
607613 }
608614 }
609615 } )
0 commit comments