|
11 | 11 | use rustc::hir::def_id::DefId;
|
12 | 12 | use rustc::ty;
|
13 | 13 | use rustc::ty::adjustment;
|
14 |
| -use util::nodemap::FxHashMap; |
15 | 14 | use lint::{LateContext, EarlyContext, LintContext, LintArray};
|
16 | 15 | use lint::{LintPass, EarlyLintPass, LateLintPass};
|
17 | 16 |
|
18 |
| -use std::collections::hash_map::Entry::{Occupied, Vacant}; |
19 |
| - |
20 | 17 | use syntax::ast;
|
21 | 18 | use syntax::attr;
|
22 | 19 | use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
|
23 | 20 | use syntax::symbol::keywords;
|
24 |
| -use syntax::ptr::P; |
25 | 21 | use syntax_pos::Span;
|
26 | 22 |
|
27 |
| -use rustc_back::slice; |
28 | 23 | use rustc::hir;
|
29 |
| -use rustc::hir::intravisit::FnKind; |
30 |
| - |
31 |
| -declare_lint! { |
32 |
| - pub UNUSED_MUT, |
33 |
| - Warn, |
34 |
| - "detect mut variables which don't need to be mutable" |
35 |
| -} |
36 |
| - |
37 |
| -#[derive(Copy, Clone)] |
38 |
| -pub struct UnusedMut; |
39 |
| - |
40 |
| -impl UnusedMut { |
41 |
| - fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) { |
42 |
| - // collect all mutable pattern and group their NodeIDs by their Identifier to |
43 |
| - // avoid false warnings in match arms with multiple patterns |
44 |
| - |
45 |
| - let mut mutables = FxHashMap(); |
46 |
| - for p in pats { |
47 |
| - p.each_binding(|_, id, span, path1| { |
48 |
| - let hir_id = cx.tcx.hir.node_to_hir_id(id); |
49 |
| - let bm = match cx.tables.pat_binding_modes().get(hir_id) { |
50 |
| - Some(&bm) => bm, |
51 |
| - None => span_bug!(span, "missing binding mode"), |
52 |
| - }; |
53 |
| - let name = path1.node; |
54 |
| - if let ty::BindByValue(hir::MutMutable) = bm { |
55 |
| - if !name.as_str().starts_with("_") { |
56 |
| - match mutables.entry(name) { |
57 |
| - Vacant(entry) => { |
58 |
| - entry.insert(vec![id]); |
59 |
| - } |
60 |
| - Occupied(mut entry) => { |
61 |
| - entry.get_mut().push(id); |
62 |
| - } |
63 |
| - } |
64 |
| - } |
65 |
| - } |
66 |
| - }); |
67 |
| - } |
68 |
| - |
69 |
| - let used_mutables = cx.tcx.used_mut_nodes.borrow(); |
70 |
| - for (_, v) in &mutables { |
71 |
| - if !v.iter().any(|e| used_mutables.contains(e)) { |
72 |
| - cx.span_lint(UNUSED_MUT, |
73 |
| - cx.tcx.hir.span(v[0]), |
74 |
| - "variable does not need to be mutable"); |
75 |
| - } |
76 |
| - } |
77 |
| - } |
78 |
| -} |
79 |
| - |
80 |
| -impl LintPass for UnusedMut { |
81 |
| - fn get_lints(&self) -> LintArray { |
82 |
| - lint_array!(UNUSED_MUT) |
83 |
| - } |
84 |
| -} |
85 |
| - |
86 |
| -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedMut { |
87 |
| - fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { |
88 |
| - if let hir::ExprMatch(_, ref arms, _) = e.node { |
89 |
| - for a in arms { |
90 |
| - self.check_unused_mut_pat(cx, &a.pats) |
91 |
| - } |
92 |
| - } |
93 |
| - } |
94 |
| - |
95 |
| - fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { |
96 |
| - if let hir::StmtDecl(ref d, _) = s.node { |
97 |
| - if let hir::DeclLocal(ref l) = d.node { |
98 |
| - self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); |
99 |
| - } |
100 |
| - } |
101 |
| - } |
102 |
| - |
103 |
| - fn check_fn(&mut self, |
104 |
| - cx: &LateContext, |
105 |
| - _: FnKind, |
106 |
| - _: &hir::FnDecl, |
107 |
| - body: &hir::Body, |
108 |
| - _: Span, |
109 |
| - _: ast::NodeId) { |
110 |
| - for a in &body.arguments { |
111 |
| - self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat)); |
112 |
| - } |
113 |
| - } |
114 |
| -} |
115 | 24 |
|
116 | 25 | declare_lint! {
|
117 | 26 | pub UNUSED_MUST_USE,
|
|
0 commit comments