Skip to content

Commit cbbdf99

Browse files
authored
Rollup merge of rust-lang#50327 - varkor:match-unused-struct-field, r=estebank
Display correct unused field suggestion for nested struct patterns Extends rust-lang#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 rust-lang#50303. r? @estebank
2 parents 30c990b + 2eb8343 commit cbbdf99

File tree

3 files changed

+120
-15
lines changed

3 files changed

+120
-15
lines changed

src/librustc/middle/liveness.rs

+35-9
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ use ty::{self, TyCtxt};
111111
use lint;
112112
use util::nodemap::{NodeMap, NodeSet};
113113

114+
use std::collections::VecDeque;
114115
use std::{fmt, usize};
115116
use std::io::prelude::*;
116117
use std::io;
@@ -412,18 +413,43 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
412413
}
413414

414415
fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
415-
for pat in &arm.pats {
416-
// for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`)
416+
for mut pat in &arm.pats {
417+
// For struct patterns, take note of which fields used shorthand
418+
// (`x` rather than `x: x`).
417419
//
418-
// FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased
419-
// out in favor of `HirId`s; however, we need to match the signature of `each_binding`,
420-
// which uses `NodeIds`.
420+
// FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be
421+
// phased out in favor of `HirId`s; however, we need to match the signature of
422+
// `each_binding`, which uses `NodeIds`.
421423
let mut shorthand_field_ids = NodeSet();
422-
if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
423-
for field in fields {
424-
if field.node.is_shorthand {
425-
shorthand_field_ids.insert(field.node.pat.id);
424+
let mut pats = VecDeque::new();
425+
pats.push_back(pat);
426+
while let Some(pat) = pats.pop_front() {
427+
use hir::PatKind::*;
428+
match pat.node {
429+
Binding(_, _, _, ref inner_pat) => {
430+
pats.extend(inner_pat.iter());
426431
}
432+
Struct(_, ref fields, _) => {
433+
for field in fields {
434+
if field.node.is_shorthand {
435+
shorthand_field_ids.insert(field.node.pat.id);
436+
}
437+
}
438+
}
439+
Ref(ref inner_pat, _) |
440+
Box(ref inner_pat) => {
441+
pats.push_back(inner_pat);
442+
}
443+
TupleStruct(_, ref inner_pats, _) |
444+
Tuple(ref inner_pats, _) => {
445+
pats.extend(inner_pats.iter());
446+
}
447+
Slice(ref pre_pats, ref inner_pat, ref post_pats) => {
448+
pats.extend(pre_pats.iter());
449+
pats.extend(inner_pat.iter());
450+
pats.extend(post_pats.iter());
451+
}
452+
_ => {}
427453
}
428454
}
429455

src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs

+43
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// compile-pass
1212

13+
#![feature(box_syntax)]
14+
#![feature(box_patterns)]
1315
#![warn(unused)] // UI tests pass `-A unused` (#43896)
1416

1517
struct SoulHistory {
@@ -18,6 +20,13 @@ struct SoulHistory {
1820
endless_and_singing: bool
1921
}
2022

23+
#[derive(Clone, Copy)]
24+
enum Large {
25+
Suit { case: () }
26+
}
27+
28+
struct Tuple(Large, ());
29+
2130
fn main() {
2231
let i_think_continually = 2;
2332
let who_from_the_womb_remembered = SoulHistory {
@@ -31,4 +40,38 @@ fn main() {
3140
endless_and_singing: true } = who_from_the_womb_remembered {
3241
hours_are_suns = false;
3342
}
43+
44+
let bag = Large::Suit {
45+
case: ()
46+
};
47+
48+
// Plain struct
49+
match bag {
50+
Large::Suit { case } => {}
51+
};
52+
53+
// Referenced struct
54+
match &bag {
55+
&Large::Suit { case } => {}
56+
};
57+
58+
// Boxed struct
59+
match box bag {
60+
box Large::Suit { case } => {}
61+
};
62+
63+
// Tuple with struct
64+
match (bag,) {
65+
(Large::Suit { case },) => {}
66+
};
67+
68+
// Slice with struct
69+
match [bag] {
70+
[Large::Suit { case }] => {}
71+
};
72+
73+
// Tuple struct with struct
74+
match Tuple(bag, ()) {
75+
Tuple(Large::Suit { case }, ()) => {}
76+
};
3477
}
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,76 @@
11
warning: unused variable: `i_think_continually`
2-
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9
2+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:31:9
33
|
44
LL | let i_think_continually = 2;
55
| ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead
66
|
77
note: lint level defined here
8-
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
8+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9
99
|
1010
LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
1111
| ^^^^^^
1212
= note: #[warn(unused_variables)] implied by #[warn(unused)]
1313

1414
warning: unused variable: `corridors_of_light`
15-
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26
15+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:26
1616
|
1717
LL | if let SoulHistory { corridors_of_light,
1818
| ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
1919

2020
warning: variable `hours_are_suns` is assigned to, but never used
21-
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26
21+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26
2222
|
2323
LL | mut hours_are_suns,
2424
| ^^^^^^^^^^^^^^^^^^
2525
|
2626
= note: consider using `_hours_are_suns` instead
2727

2828
warning: value assigned to `hours_are_suns` is never read
29-
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9
29+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9
3030
|
3131
LL | hours_are_suns = false;
3232
| ^^^^^^^^^^^^^^
3333
|
3434
note: lint level defined here
35-
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
35+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9
3636
|
3737
LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
3838
| ^^^^^^
3939
= note: #[warn(unused_assignments)] implied by #[warn(unused)]
4040

41+
warning: unused variable: `case`
42+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:23
43+
|
44+
LL | Large::Suit { case } => {}
45+
| ^^^^ help: try ignoring the field: `case: _`
46+
47+
warning: unused variable: `case`
48+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:55:24
49+
|
50+
LL | &Large::Suit { case } => {}
51+
| ^^^^ help: try ignoring the field: `case: _`
52+
53+
warning: unused variable: `case`
54+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:60:27
55+
|
56+
LL | box Large::Suit { case } => {}
57+
| ^^^^ help: try ignoring the field: `case: _`
58+
59+
warning: unused variable: `case`
60+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:65:24
61+
|
62+
LL | (Large::Suit { case },) => {}
63+
| ^^^^ help: try ignoring the field: `case: _`
64+
65+
warning: unused variable: `case`
66+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:70:24
67+
|
68+
LL | [Large::Suit { case }] => {}
69+
| ^^^^ help: try ignoring the field: `case: _`
70+
71+
warning: unused variable: `case`
72+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:75:29
73+
|
74+
LL | Tuple(Large::Suit { case }, ()) => {}
75+
| ^^^^ help: try ignoring the field: `case: _`
76+

0 commit comments

Comments
 (0)