diff --git a/src/analyze/local_def.rs b/src/analyze/local_def.rs index 6a9cdf1b..7f0b8beb 100644 --- a/src/analyze/local_def.rs +++ b/src/analyze/local_def.rs @@ -461,8 +461,12 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> { fn unelaborate_derefs(&mut self) { let mut v = analyze::ReplacePlacesVisitor::new(self.tcx); - for (block, data) in self.body.basic_blocks.clone().iter_enumerated() { - for (idx, _stmt) in data.statements.iter().enumerate() { + // A deref temp must be replaced in every block that uses it, and block indices do not + // follow dominance: drop elaboration can number a cleanup block before the one that + // defines the temp it uses. + for block in self.body.basic_blocks.reverse_postorder().to_vec() { + let statement_count = self.body.basic_blocks[block].statements.len(); + for idx in 0..statement_count { let stmt = &mut self.body.basic_blocks.as_mut().as_mut_slice()[block].statements[idx]; v.visit_statement(stmt); diff --git a/tests/ui/fail/box_move_out_after_call.rs b/tests/ui/fail/box_move_out_after_call.rs new file mode 100644 index 00000000..a3830ad5 --- /dev/null +++ b/tests/ui/fail/box_move_out_after_call.rs @@ -0,0 +1,12 @@ +//@error-in-other-file: Unsat +//@compile-flags: -C debug-assertions=off + +fn add(bb: Box>, x: i64) -> i64 { + let c = Box::new(x); + let inner = *bb; + *inner + *c +} + +fn main() { + assert!(add(Box::new(Box::new(1)), 2) == 4); +} diff --git a/tests/ui/pass/box_move_out_after_call.rs b/tests/ui/pass/box_move_out_after_call.rs new file mode 100644 index 00000000..66bb2d8f --- /dev/null +++ b/tests/ui/pass/box_move_out_after_call.rs @@ -0,0 +1,12 @@ +//@check-pass +//@compile-flags: -C debug-assertions=off + +fn add(bb: Box>, x: i64) -> i64 { + let c = Box::new(x); + let inner = *bb; + *inner + *c +} + +fn main() { + assert!(add(Box::new(Box::new(1)), 2) == 3); +}