diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index abfc2f9466c..4a4787337ab 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -52,6 +52,19 @@ struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> { mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, } +impl GatherUsedMutsVisitor<'_, '_, '_, '_> { + fn remove_never_initialized_mut_locals(&mut self, into: &Place<'_>) { + // Remove any locals that we found were initialized from the + // `never_initialized_mut_locals` set. At the end, the only remaining locals will + // be those that were never initialized - we will consider those as being used as + // they will either have been removed by unreachable code optimizations; or linted + // as unused variables. + if let Some(local) = into.base_local() { + let _ = self.never_initialized_mut_locals.remove(&local); + } + } +} + impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> { fn visit_terminator_kind( &mut self, @@ -61,14 +74,10 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c debug!("visit_terminator_kind: kind={:?}", kind); match &kind { TerminatorKind::Call { destination: Some((into, _)), .. } => { - if let Some(local) = into.base_local() { - debug!( - "visit_terminator_kind: kind={:?} local={:?} \ - never_initialized_mut_locals={:?}", - kind, local, self.never_initialized_mut_locals - ); - let _ = self.never_initialized_mut_locals.remove(&local); - } + self.remove_never_initialized_mut_locals(&into); + }, + TerminatorKind::DropAndReplace { location, .. } => { + self.remove_never_initialized_mut_locals(&location); }, _ => {}, } @@ -81,19 +90,14 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c ) { match &statement.kind { StatementKind::Assign(into, _) => { - // Remove any locals that we found were initialized from the - // `never_initialized_mut_locals` set. At the end, the only remaining locals will - // be those that were never initialized - we will consider those as being used as - // they will either have been removed by unreachable code optimizations; or linted - // as unused variables. if let Some(local) = into.base_local() { debug!( "visit_statement: statement={:?} local={:?} \ never_initialized_mut_locals={:?}", statement, local, self.never_initialized_mut_locals ); - let _ = self.never_initialized_mut_locals.remove(&local); } + self.remove_never_initialized_mut_locals(into); }, _ => {}, } diff --git a/src/test/ui/nll/issue-61424.rs b/src/test/ui/nll/issue-61424.rs new file mode 100644 index 00000000000..44c8e9f7256 --- /dev/null +++ b/src/test/ui/nll/issue-61424.rs @@ -0,0 +1,7 @@ +#![deny(unused_mut)] + +fn main() { + let mut x; //~ ERROR: variable does not need to be mutable + x = String::new(); + dbg!(x); +} diff --git a/src/test/ui/nll/issue-61424.stderr b/src/test/ui/nll/issue-61424.stderr new file mode 100644 index 00000000000..ae336b2fe1c --- /dev/null +++ b/src/test/ui/nll/issue-61424.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/issue-61424.rs:4:9 + | +LL | let mut x; + | ----^ + | | + | help: remove this `mut` + | +note: lint level defined here + --> $DIR/issue-61424.rs:1:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error +