diff --git a/src/analyze/local_def.rs b/src/analyze/local_def.rs index f1f5bdd2..cf5eaf63 100644 --- a/src/analyze/local_def.rs +++ b/src/analyze/local_def.rs @@ -649,13 +649,15 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> { } fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: mir::Location) { - if let mir::Operand::Move(place) = operand { - // to be reborrowed; see analyze::basic_block::visitor - if place - .ty(&self.body.local_decls, self.tcx) - .ty - .is_mutable_ptr() - { + // to be reborrowed; see analyze::basic_block::visitor. A `&mut` + // field read out of an aggregate is `copy (_1.0)`, so match Copy + // too to mark the base local. Reference only: `is_mutable_ptr()` + // also covers `*mut`, which is Copy but never reborrowed. + if let mir::Operand::Move(place) | mir::Operand::Copy(place) = operand { + if matches!( + place.ty(&self.body.local_decls, self.tcx).ty.kind(), + mir_ty::TyKind::Ref(_, _, m) if m.is_mut() + ) { self.locals.insert(place.local); } } diff --git a/tests/ui/fail/reborrow_mut_field_of_aggregate_param.rs b/tests/ui/fail/reborrow_mut_field_of_aggregate_param.rs new file mode 100644 index 00000000..d5451ea6 --- /dev/null +++ b/tests/ui/fail/reborrow_mut_field_of_aggregate_param.rs @@ -0,0 +1,18 @@ +//@error-in-other-file: Unsat + +// Regression test for #125: reborrowing a `&mut` field out of an aggregate +// parameter used to panic with "deref unbound var". + +fn bump(r: &mut i64) { + *r = 1; +} + +fn f(w: (&mut i64,)) { + bump(w.0); +} + +fn main() { + let mut x = 0_i64; + f((&mut x,)); + assert!(x == 0); +} diff --git a/tests/ui/pass/reborrow_mut_field_of_aggregate_param.rs b/tests/ui/pass/reborrow_mut_field_of_aggregate_param.rs new file mode 100644 index 00000000..89a855d6 --- /dev/null +++ b/tests/ui/pass/reborrow_mut_field_of_aggregate_param.rs @@ -0,0 +1,18 @@ +//@check-pass + +// Regression test for #125: reborrowing a `&mut` field out of an aggregate +// parameter used to panic with "deref unbound var". + +fn bump(r: &mut i64) { + *r = 1; +} + +fn f(w: (&mut i64,)) { + bump(w.0); +} + +fn main() { + let mut x = 0_i64; + f((&mut x,)); + assert!(x == 1); +}