diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b32ee2f29d22e..d1a46f5f15563 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 db3c812f259c0..6994a377a06d7 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 ce064f9c93fc3..7bfe2c9162ed1 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: _` +