]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #50327 - varkor:match-unused-struct-field, r=estebank
authorkennytm <kennytm@gmail.com>
Mon, 30 Apr 2018 17:18:40 +0000 (01:18 +0800)
committerGitHub <noreply@github.com>
Mon, 30 Apr 2018 17:18:40 +0000 (01:18 +0800)
Display correct unused field suggestion for nested struct patterns

Extends https://github.com/rust-lang/rust/pull/47922 by checking more sophisticated patterns (e.g. references, slices, etc.).
Before:
```
warning: unused variable: `bar`
  --> src/main.rs:37:21
   |
37 |         &Foo::Bar { bar } => true,
   |                     ^^^ help: consider using `_bar` instead
   |
   = note: #[warn(unused_variables)] on by default
```
After:
```
warning: unused variable: `bar`
  --> src/main.rs:37:21
   |
37 |         &Foo::Bar { bar } => true,
   |                     ^^^ help: try ignoring the field: `bar: _`
   |
   = note: #[warn(unused_variables)] on by default
```

Fixes #50303.

r? @estebank

src/librustc/middle/liveness.rs
src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr

index 17c114bc3b3c0f3beff9483681aa136d30f6b221..d1a46f5f155637f02624592f1e9d127436a87425 100644 (file)
 use lint;
 use util::nodemap::{NodeMap, NodeSet};
 
+use std::collections::VecDeque;
 use std::{fmt, usize};
 use std::io::prelude::*;
 use std::io;
@@ -412,18 +413,43 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
 }
 
 fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
-    for pat in &arm.pats {
-        // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`)
+    for mut pat in &arm.pats {
+        // For struct patterns, take note of which fields used shorthand
+        // (`x` rather than `x: x`).
         //
-        // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased
-        // out in favor of `HirId`s; however, we need to match the signature of `each_binding`,
-        // which uses `NodeIds`.
+        // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be
+        // phased out in favor of `HirId`s; however, we need to match the signature of
+        // `each_binding`, which uses `NodeIds`.
         let mut shorthand_field_ids = NodeSet();
-        if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
-            for field in fields {
-                if field.node.is_shorthand {
-                    shorthand_field_ids.insert(field.node.pat.id);
+        let mut pats = VecDeque::new();
+        pats.push_back(pat);
+        while let Some(pat) = pats.pop_front() {
+            use hir::PatKind::*;
+            match pat.node {
+                Binding(_, _, _, ref inner_pat) => {
+                    pats.extend(inner_pat.iter());
                 }
+                Struct(_, ref fields, _) => {
+                    for field in fields {
+                        if field.node.is_shorthand {
+                            shorthand_field_ids.insert(field.node.pat.id);
+                        }
+                    }
+                }
+                Ref(ref inner_pat, _) |
+                Box(ref inner_pat) => {
+                    pats.push_back(inner_pat);
+                }
+                TupleStruct(_, ref inner_pats, _) |
+                Tuple(ref inner_pats, _) => {
+                    pats.extend(inner_pats.iter());
+                }
+                Slice(ref pre_pats, ref inner_pat, ref post_pats) => {
+                    pats.extend(pre_pats.iter());
+                    pats.extend(inner_pat.iter());
+                    pats.extend(post_pats.iter());
+                }
+                _ => {}
             }
         }
 
index 18b83370355b644e8dc5ea646c1df9c64489ec8c..6994a377a06d7c01373dca5bc51034f61bbec92d 100644 (file)
@@ -10,6 +10,8 @@
 
 // compile-pass
 
+#![feature(box_syntax)]
+#![feature(box_patterns)]
 #![warn(unused)] // UI tests pass `-A unused` (#43896)
 
 struct SoulHistory {
@@ -18,6 +20,13 @@ struct SoulHistory {
     endless_and_singing: bool
 }
 
+#[derive(Clone, Copy)]
+enum Large {
+    Suit { case: () }
+}
+
+struct Tuple(Large, ());
+
 fn main() {
     let i_think_continually = 2;
     let who_from_the_womb_remembered = SoulHistory {
@@ -31,4 +40,38 @@ fn main() {
                          endless_and_singing: true } = who_from_the_womb_remembered {
         hours_are_suns = false;
     }
+
+    let bag = Large::Suit {
+        case: ()
+    };
+
+    // Plain struct
+    match bag {
+        Large::Suit { case } => {}
+    };
+
+    // Referenced struct
+    match &bag {
+        &Large::Suit { case } => {}
+    };
+
+    // Boxed struct
+    match box bag {
+        box Large::Suit { case } => {}
+    };
+
+    // Tuple with struct
+    match (bag,) {
+        (Large::Suit { case },) => {}
+    };
+
+    // Slice with struct
+    match [bag] {
+        [Large::Suit { case }] => {}
+    };
+
+    // Tuple struct with struct
+    match Tuple(bag, ()) {
+        Tuple(Large::Suit { case }, ()) => {}
+    };
 }
index 35fe5479406df85c0e17e0985169e53924d9a17e..7bfe2c9162ed17d9a30936a164989645d8bea17f 100644 (file)
@@ -1,24 +1,24 @@
 warning: unused variable: `i_think_continually`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:31:9
    |
 LL |     let i_think_continually = 2;
    |         ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead
    |
 note: lint level defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9
    |
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_variables)] implied by #[warn(unused)]
 
 warning: unused variable: `corridors_of_light`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:26
    |
 LL |     if let SoulHistory { corridors_of_light,
    |                          ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
 
 warning: variable `hours_are_suns` is assigned to, but never used
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26
    |
 LL |                          mut hours_are_suns,
    |                          ^^^^^^^^^^^^^^^^^^
@@ -26,15 +26,51 @@ LL |                          mut hours_are_suns,
    = note: consider using `_hours_are_suns` instead
 
 warning: value assigned to `hours_are_suns` is never read
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9
    |
 LL |         hours_are_suns = false;
    |         ^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9
    |
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_assignments)] implied by #[warn(unused)]
 
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:23
+   |
+LL |         Large::Suit { case } => {}
+   |                       ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:55:24
+   |
+LL |         &Large::Suit { case } => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:60:27
+   |
+LL |         box Large::Suit { case } => {}
+   |                           ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:65:24
+   |
+LL |         (Large::Suit { case },) => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:70:24
+   |
+LL |         [Large::Suit { case }] => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:75:29
+   |
+LL |         Tuple(Large::Suit { case }, ()) => {}
+   |                             ^^^^ help: try ignoring the field: `case: _`
+