about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2021-02-23 16:10:25 +0100
committerGitHub <noreply@github.com>2021-02-23 16:10:25 +0100
commit9d378b33defb2edcacadc4fd5fb0e9329f9d1eec (patch)
treec375279bb20fa57dc840f47552c531457addde0f /compiler/rustc_passes/src
parente2561c58a41023a14e0e583113dcf55e1ecb236a (diff)
parent343b67387772dbd068d06a76267288579d3eaed0 (diff)
downloadrust-9d378b33defb2edcacadc4fd5fb0e9329f9d1eec.tar.gz
rust-9d378b33defb2edcacadc4fd5fb0e9329f9d1eec.zip
Rollup merge of #82297 - tmiasko:write-only, r=oli-obk
Consider auto derefs before warning about write only fields

Changes from #81473 extended the dead code lint with an ability to detect
fields that are written to but never read from. The implementation skips
over fields on the left hand side of an assignment, without marking them
as live.

A field access might involve an automatic dereference and de-facto read
the field. Conservatively mark expressions with deref adjustments as
live to avoid generating false positive warnings.

Closes #81626.
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/dead.rs28
1 files changed, 17 insertions, 11 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d51b501f7ae..62a95aa57c2 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -37,15 +37,6 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
     )
 }
 
-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,
-        }
-    }
-}
-
 struct MarkSymbolVisitor<'tcx> {
     worklist: Vec<hir::HirId>,
     tcx: TyCtxt<'tcx>,
@@ -143,6 +134,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
     }
 
+    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);
+        }
+    }
+
     fn handle_field_pattern_match(
         &mut self,
         lhs: &hir::Pat<'_>,
@@ -272,8 +279,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
                 self.lookup_and_handle_method(expr.hir_id);
             }
             hir::ExprKind::Assign(ref left, ref right, ..) => {
-                // Ignore write to field
-                self.visit_expr(base_expr(left));
+                self.handle_assign(left);
                 self.visit_expr(right);
                 return;
             }