Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --Here's a reduced test-case from Firefox source code: Compiling that program warns with: Which is obviously not true. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
Seems like this is a regression from .
cc
Oops, sorry! Technically, field is, in fact, never read. What went wrong is is written and read through other ways. I think restricting the lint to non-reference fields should work, and will submit a PR to do so quickly. Please double check whether my thinking is correct.
Ah, yeah, I somehow thought that the macro was needed to trigger the bug but it is not. That sounds good. Writes to mutable references have side effects so doing that seems ok.
Would that also cover this case here, in the idna crate? (The field is a reference to an type, which is in fact returned to the caller of .)
Yeah, I think it's the same.
Ah, this was closed, but the bug leaked into beta (as mentioned in ) while the fix is only in nightly. Reopening and tagging as stable-to-beta regression
Assigning and removing .
As noted on , we're going to resolve the beta issue by reverting PR on beta (which I have assigned myself to take care of).
This was a regression affecting beta 1.51, closing this.

Discussion:
) } <del> fn base_expr<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { loop { match expr.kind { hir::ExprKind::Field(base, ..) => expr = base, _ => return expr, } } } </del> struct MarkSymbolVisitor<'tcx> { worklist: Vec<hir::HirId>, tcx: TyCtxt<'tcx>,

} } <ins> fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) { if self .typeck_results() .expr_adjustments(expr) .iter() .any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_))) { self.visit_expr(expr); } else if let hir::ExprKind::Field(base, ..) = expr.kind { // Ignore write to field self.handle_assign(base); } else { self.visit_expr(expr); } } </ins> fn handle_field_pattern_match( &mut self, lhs: &hir::Pat<'_>,

self.lookup_and_handle_method(expr.hir_id); } hir::ExprKind::Assign(ref left, ref right, ..) => { <del> // Ignore write to field self.visit_expr(base_expr(left)); </del> <ins> self.handle_assign(left); </ins> self.visit_expr(right); return; }

fn main() { let mut s = S { f: 0, sub: Sub { f: 0 } }; field_write(&mut s); <ins> auto_deref(); nested_boxes(); } fn auto_deref() { struct E { x: bool, y: bool, //~ ERROR: field is never read } struct P<'a> { e: &'a mut E } impl P<'_> { fn f(&mut self) { self.e.x = true; self.e.y = true; } } let mut e = E { x: false, y: false }; let mut p = P { e: &mut e }; p.f(); assert!(e.x); } fn nested_boxes() { struct A { b: Box<B>, } struct B { c: Box<C>, } struct C { u: u32, //~ ERROR: field is never read v: u32, //~ ERROR: field is never read } let mut a = A { b: Box::new(B { c: Box::new(C { u: 0, v: 0 }), }), }; a.b.c.v = 10; a.b.c = Box::new(C { u: 1, v: 2 }); </ins> }

LL |     f: i32, |     ^^^^^^ <del> error: aborting due to 3 previous errors </del> <ins> error: field is never read: `y` --> $DIR/write-only-field.rs:28:9 | LL |         y: bool, |         ^^^^^^^ error: field is never read: `u` --> $DIR/write-only-field.rs:58:9 | LL |         u: u32, |         ^^^^^^ error: field is never read: `v` --> $DIR/write-only-field.rs:59:9 | LL |         v: u32, |         ^^^^^^ error: aborting due to 6 previous errors </ins>