Skip to content

Commit 0ba8712

Browse files
authored
Rollup merge of rust-lang#47922 - zackmdavis:and_the_case_of_the_unused_field_pattern, r=estebank
correct unused field pattern suggestions ![unused_field_pattern_local](https://user-images.githubusercontent.com/1076988/35662336-7a69488a-06cc-11e8-9901-8d22b5cf924f.png) r? @estebank
2 parents d2f7feb + e4b1a79 commit 0ba8712

5 files changed

+127
-17
lines changed

src/librustc/middle/liveness.rs

+49-14
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ use self::VarKind::*;
109109
use hir::def::*;
110110
use ty::{self, TyCtxt};
111111
use lint;
112-
use util::nodemap::NodeMap;
112+
use util::nodemap::{NodeMap, NodeSet};
113113

114114
use std::{fmt, usize};
115115
use std::io::prelude::*;
@@ -244,7 +244,8 @@ struct CaptureInfo {
244244
#[derive(Copy, Clone, Debug)]
245245
struct LocalInfo {
246246
id: NodeId,
247-
name: ast::Name
247+
name: ast::Name,
248+
is_shorthand: bool,
248249
}
249250

250251
#[derive(Copy, Clone, Debug)]
@@ -333,6 +334,13 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
333334
}
334335
}
335336

337+
fn variable_is_shorthand(&self, var: Variable) -> bool {
338+
match self.var_kinds[var.get()] {
339+
Local(LocalInfo { is_shorthand, .. }) => is_shorthand,
340+
Arg(..) | CleanExit => false
341+
}
342+
}
343+
336344
fn set_captures(&mut self, node_id: NodeId, cs: Vec<CaptureInfo>) {
337345
self.capture_info_map.insert(node_id, Rc::new(cs));
338346
}
@@ -384,23 +392,41 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
384392
let name = path1.node;
385393
ir.add_live_node_for_node(p_id, VarDefNode(sp));
386394
ir.add_variable(Local(LocalInfo {
387-
id: p_id,
388-
name,
395+
id: p_id,
396+
name,
397+
is_shorthand: false,
389398
}));
390399
});
391400
intravisit::walk_local(ir, local);
392401
}
393402

394403
fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
395404
for pat in &arm.pats {
405+
// for struct patterns, take note of which fields used shorthand (`x`
406+
// rather than `x: x`)
407+
//
408+
// FIXME: according to the rust-lang-nursery/rustc-guide book and
409+
// librustc/README.md, `NodeId`s are to be phased out in favor of
410+
// `HirId`s; however, we need to match the signature of `each_binding`,
411+
// which uses `NodeIds`.
412+
let mut shorthand_field_ids = NodeSet();
413+
if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
414+
for field in fields {
415+
if field.node.is_shorthand {
416+
shorthand_field_ids.insert(field.node.pat.id);
417+
}
418+
}
419+
}
420+
396421
pat.each_binding(|bm, p_id, sp, path1| {
397422
debug!("adding local variable {} from match with bm {:?}",
398423
p_id, bm);
399424
let name = path1.node;
400425
ir.add_live_node_for_node(p_id, VarDefNode(sp));
401426
ir.add_variable(Local(LocalInfo {
402427
id: p_id,
403-
name,
428+
name: name,
429+
is_shorthand: shorthand_field_ids.contains(&p_id)
404430
}));
405431
})
406432
}
@@ -1483,17 +1509,26 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
14831509
self.assigned_on_exit(ln, var).is_some()
14841510
};
14851511

1512+
let suggest_underscore_msg = format!("consider using `_{}` instead",
1513+
name);
14861514
if is_assigned {
1487-
self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
1488-
&format!("variable `{}` is assigned to, but never used",
1489-
name),
1490-
&format!("to avoid this warning, consider using `_{}` instead",
1491-
name));
1515+
self.ir.tcx
1516+
.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
1517+
&format!("variable `{}` is assigned to, but never used",
1518+
name),
1519+
&suggest_underscore_msg);
14921520
} else if name != "self" {
1493-
self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
1494-
&format!("unused variable: `{}`", name),
1495-
&format!("to avoid this warning, consider using `_{}` instead",
1496-
name));
1521+
let msg = format!("unused variable: `{}`", name);
1522+
let mut err = self.ir.tcx
1523+
.struct_span_lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, &msg);
1524+
if self.ir.variable_is_shorthand(var) {
1525+
err.span_suggestion(sp, "try ignoring the field",
1526+
format!("{}: _", name));
1527+
} else {
1528+
err.span_suggestion_short(sp, &suggest_underscore_msg,
1529+
format!("_{}", name));
1530+
}
1531+
err.emit()
14971532
}
14981533
}
14991534
true

src/librustc/util/nodemap.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,20 @@
1313
#![allow(non_snake_case)]
1414

1515
use hir::def_id::DefId;
16-
use hir::ItemLocalId;
16+
use hir::{HirId, ItemLocalId};
1717
use syntax::ast;
1818

1919
pub use rustc_data_structures::fx::FxHashMap;
2020
pub use rustc_data_structures::fx::FxHashSet;
2121

2222
pub type NodeMap<T> = FxHashMap<ast::NodeId, T>;
2323
pub type DefIdMap<T> = FxHashMap<DefId, T>;
24+
pub type HirIdMap<T> = FxHashMap<HirId, T>;
2425
pub type ItemLocalMap<T> = FxHashMap<ItemLocalId, T>;
2526

2627
pub type NodeSet = FxHashSet<ast::NodeId>;
2728
pub type DefIdSet = FxHashSet<DefId>;
29+
pub type HirIdSet = FxHashSet<HirId>;
2830
pub type ItemLocalSet = FxHashSet<ItemLocalId>;
2931

3032
pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// must-compile-successfully
12+
13+
#![warn(unused)] // UI tests pass `-A unused` (#43896)
14+
15+
struct SoulHistory {
16+
corridors_of_light: usize,
17+
hours_are_suns: bool,
18+
endless_and_singing: bool
19+
}
20+
21+
fn main() {
22+
let i_think_continually = 2;
23+
let who_from_the_womb_remembered = SoulHistory {
24+
corridors_of_light: 5,
25+
hours_are_suns: true,
26+
endless_and_singing: true
27+
};
28+
29+
if let SoulHistory { corridors_of_light,
30+
mut hours_are_suns,
31+
endless_and_singing: true } = who_from_the_womb_remembered {
32+
hours_are_suns = false;
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
warning: unused variable: `i_think_continually`
2+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9
3+
|
4+
22 | let i_think_continually = 2;
5+
| ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead
6+
|
7+
note: lint level defined here
8+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
9+
|
10+
13 | #![warn(unused)] // UI tests pass `-A unused` (#43896)
11+
| ^^^^^^
12+
= note: #[warn(unused_variables)] implied by #[warn(unused)]
13+
14+
warning: unused variable: `corridors_of_light`
15+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26
16+
|
17+
29 | if let SoulHistory { corridors_of_light,
18+
| ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
19+
20+
warning: variable `hours_are_suns` is assigned to, but never used
21+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26
22+
|
23+
30 | mut hours_are_suns,
24+
| ^^^^^^^^^^^^^^^^^^
25+
|
26+
= note: consider using `_hours_are_suns` instead
27+
28+
warning: value assigned to `hours_are_suns` is never read
29+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9
30+
|
31+
32 | hours_are_suns = false;
32+
| ^^^^^^^^^^^^^^
33+
|
34+
note: lint level defined here
35+
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
36+
|
37+
13 | #![warn(unused)] // UI tests pass `-A unused` (#43896)
38+
| ^^^^^^
39+
= note: #[warn(unused_assignments)] implied by #[warn(unused)]
40+

src/test/ui/span/issue-24690.stderr

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ warning: unused variable: `theOtherTwo`
22
--> $DIR/issue-24690.rs:23:9
33
|
44
23 | let theOtherTwo = 2; //~ WARN should have a snake case name
5-
| ^^^^^^^^^^^
5+
| ^^^^^^^^^^^ help: consider using `_theOtherTwo` instead
66
|
77
note: lint level defined here
88
--> $DIR/issue-24690.rs:18:9
99
|
1010
18 | #![warn(unused)]
1111
| ^^^^^^
1212
= note: #[warn(unused_variables)] implied by #[warn(unused)]
13-
= note: to avoid this warning, consider using `_theOtherTwo` instead
1413

1514
warning: variable `theTwo` should have a snake case name such as `the_two`
1615
--> $DIR/issue-24690.rs:22:9

0 commit comments

Comments
 (0)