Change:
(sorry if this is an duplicate or the wrong repo :innocent: ) () Current behavior: no warning Expected behavior: The variable clearly doesn't need to be mutable, still, nothing is detected and no warning is emitted. Rust 1.35.0 (Using the , also in ())
The warning appears again if you switch to 2015 edition. Huh. Nice catch!
I found that Stable 2015 edition produces the warning and everything else doesn't.
cc (likely caused by NLL migrate mode, which was enabled in for the 2015 edition)
Yes, looks like another nll bug. If someone wants to have a go at this, the issue is that we are treating DropAndReplace differently to Assign for the purposes of this lint.
I can try doing it I just don't know here to begin.
I don't know this code too well, but take a look at . The first thing I'd try is adding a case for to the match in that mirrors what's done for .
Makes sense thank you. I was looking at librustc_lint and couldn't find anything.

Discussion:
mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, } <ins> 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); } } } </ins> impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> { fn visit_terminator_kind( &mut self,

debug!("visit_terminator_kind: kind={:?}", kind); match &kind { TerminatorKind::Call { destination: Some((into, _)), .. } => { <del> 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); } </del> <ins> self.remove_never_initialized_mut_locals(&into); }, TerminatorKind::DropAndReplace { location, .. } => { self.remove_never_initialized_mut_locals(&location); </ins> }, _ => {}, }

) { match &statement.kind { StatementKind::Assign(into, _) => { <del> // 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. </del> if let Some(local) = into.base_local() { debug!( "visit_statement: statement={:?} local={:?}  never_initialized_mut_locals={:?}", statement, local, self.never_initialized_mut_locals ); <del> let _ = self.never_initialized_mut_locals.remove(&local); </del> } <ins> self.remove_never_initialized_mut_locals(into); </ins> }, _ => {}, }

<ins> #![deny(unused_mut)] fn main() { let mut x; //~ ERROR: variable does not need to be mutable x = String::new(); dbg!(x); } </ins>

<ins> 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 </ins>