about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2018-04-30 01:27:37 +0100
committervarkor <github@varkor.com>2018-04-30 01:27:37 +0100
commit2eb8343af18470d3c48a50c68dbaeb1887b42c37 (patch)
tree6f97cfbaa41fd0d2cfdcde2b0545ea913cd291e0
parent8e8fe9042c86c53d90ce17cc0754505bf014d0ed (diff)
downloadrust-2eb8343af18470d3c48a50c68dbaeb1887b42c37.tar.gz
rust-2eb8343af18470d3c48a50c68dbaeb1887b42c37.zip
Correct unused field warning on struct match container patterns
-rw-r--r--src/librustc/middle/liveness.rs29
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs25
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr36
3 files changed, 77 insertions, 13 deletions
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index b32ee2f29d2..d1a46f5f155 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -111,6 +111,7 @@ use ty::{self, TyCtxt};
 use lint;
 use util::nodemap::{NodeMap, NodeSet};
 
+use std::collections::VecDeque;
 use std::{fmt, usize};
 use std::io::prelude::*;
 use std::io;
@@ -420,21 +421,35 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
         // 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();
-        loop {
+        let mut pats = VecDeque::new();
+        pats.push_back(pat);
+        while let Some(pat) = pats.pop_front() {
+            use hir::PatKind::*;
             match pat.node {
-                hir::PatKind::Struct(_, ref fields, _) => {
+                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);
                         }
                     }
-                    break;
                 }
-                hir::PatKind::Ref(ref inner_pat, _) |
-                hir::PatKind::Box(ref inner_pat) => {
-                    pat = inner_pat;
+                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());
                 }
-                _ => break
+                _ => {}
             }
         }
 
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
index db3c812f259..6994a377a06 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
@@ -20,10 +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 {
@@ -42,11 +45,33 @@ fn main() {
         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 }, ()) => {}
+    };
 }
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
index ce064f9c93f..7bfe2c9162e 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -1,5 +1,5 @@
 warning: unused variable: `i_think_continually`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:28: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
@@ -12,13 +12,13 @@ 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:35: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:36:26
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26
    |
 LL |                          mut hours_are_suns,
    |                          ^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ 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:38:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9
    |
 LL |         hours_are_suns = false;
    |         ^^^^^^^^^^^^^^
@@ -39,14 +39,38 @@ 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:46:24
+  --> $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:50:27
+  --> $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: _`
+