about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-01-30 13:36:52 +0900
committerGitHub <noreply@github.com>2021-01-30 13:36:52 +0900
commit774ba83226d570d2ac4dd072515d3cbd08bd5b3e (patch)
treeab65ee274799b04f810e433cae76e375d37e6000
parentfe27dea4b5f3ae1fe95a16f2bd9c6428fdd116b5 (diff)
parent85ad773049536d7fed9a94ae0ac74f97135c8655 (diff)
downloadrust-774ba83226d570d2ac4dd072515d3cbd08bd5b3e.tar.gz
rust-774ba83226d570d2ac4dd072515d3cbd08bd5b3e.zip
Rollup merge of #81473 - sanxiyn:write-only-field, r=oli-obk
Warn write-only fields

cc `@Boscop's` example in #49256.
-rw-r--r--compiler/rustc_passes/src/dead.rs15
-rw-r--r--src/test/ui/borrowck/borrowck-assign-to-subfield.rs1
-rw-r--r--src/test/ui/lint/dead-code/write-only-field.rs20
-rw-r--r--src/test/ui/lint/dead-code/write-only-field.stderr26
4 files changed, 62 insertions, 0 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 3b1b53553d5..0d096a0556b 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -37,6 +37,15 @@ 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>,
@@ -263,6 +272,12 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
             hir::ExprKind::MethodCall(..) => {
                 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.visit_expr(right);
+                return;
+            }
             hir::ExprKind::Field(ref lhs, ..) => {
                 self.handle_field_access(&lhs, expr.hir_id);
             }
diff --git a/src/test/ui/borrowck/borrowck-assign-to-subfield.rs b/src/test/ui/borrowck/borrowck-assign-to-subfield.rs
index 050d702b625..dfa3a561ec7 100644
--- a/src/test/ui/borrowck/borrowck-assign-to-subfield.rs
+++ b/src/test/ui/borrowck/borrowck-assign-to-subfield.rs
@@ -1,5 +1,6 @@
 // run-pass
 // pretty-expanded FIXME #23616
+#![allow(dead_code)]
 
 pub fn main() {
     struct A {
diff --git a/src/test/ui/lint/dead-code/write-only-field.rs b/src/test/ui/lint/dead-code/write-only-field.rs
new file mode 100644
index 00000000000..78cfcfda8f9
--- /dev/null
+++ b/src/test/ui/lint/dead-code/write-only-field.rs
@@ -0,0 +1,20 @@
+#![deny(dead_code)]
+
+struct S {
+    f: i32, //~ ERROR: field is never read
+    sub: Sub, //~ ERROR: field is never read
+}
+
+struct Sub {
+    f: i32, //~ ERROR: field is never read
+}
+
+fn field_write(s: &mut S) {
+    s.f = 1;
+    s.sub.f = 2;
+}
+
+fn main() {
+    let mut s = S { f: 0, sub: Sub { f: 0 } };
+    field_write(&mut s);
+}
diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr
new file mode 100644
index 00000000000..70d2149665b
--- /dev/null
+++ b/src/test/ui/lint/dead-code/write-only-field.stderr
@@ -0,0 +1,26 @@
+error: field is never read: `f`
+  --> $DIR/write-only-field.rs:4:5
+   |
+LL |     f: i32,
+   |     ^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/write-only-field.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field is never read: `sub`
+  --> $DIR/write-only-field.rs:5:5
+   |
+LL |     sub: Sub,
+   |     ^^^^^^^^
+
+error: field is never read: `f`
+  --> $DIR/write-only-field.rs:9:5
+   |
+LL |     f: i32,
+   |     ^^^^^^
+
+error: aborting due to 3 previous errors
+