]> git.proxmox.com Git - rustc.git/blame - src/librustc_borrowck/borrowck/unused.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / librustc_borrowck / borrowck / unused.rs
CommitLineData
abe05a73
XL
1// Copyright 2017 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
11use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
12use rustc::hir::{self, HirId};
13use rustc::lint::builtin::UNUSED_MUT;
14use rustc::ty;
15use rustc::util::nodemap::{FxHashMap, FxHashSet};
ff7c6d11 16use std::slice;
abe05a73
XL
17use syntax::ptr::P;
18
19use borrowck::BorrowckCtxt;
20
21pub fn check<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: &'tcx hir::Body) {
22 let mut used_mut = bccx.used_mut_nodes.borrow().clone();
23 UsedMutFinder {
24 bccx,
25 set: &mut used_mut,
26 }.visit_expr(&body.value);
27 let mut cx = UnusedMutCx { bccx, used_mut };
28 for arg in body.arguments.iter() {
ff7c6d11 29 cx.check_unused_mut_pat(slice::from_ref(&arg.pat));
abe05a73
XL
30 }
31 cx.visit_expr(&body.value);
32}
33
34struct UsedMutFinder<'a, 'tcx: 'a> {
35 bccx: &'a BorrowckCtxt<'a, 'tcx>,
36 set: &'a mut FxHashSet<HirId>,
37}
38
39struct UnusedMutCx<'a, 'tcx: 'a> {
40 bccx: &'a BorrowckCtxt<'a, 'tcx>,
41 used_mut: FxHashSet<HirId>,
42}
43
44impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> {
45 fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
46 let tcx = self.bccx.tcx;
47 let mut mutables = FxHashMap();
48 for p in pats {
94b46f34 49 p.each_binding(|_, hir_id, span, path1| {
abe05a73
XL
50 let name = path1.node;
51
52 // Skip anything that looks like `_foo`
53 if name.as_str().starts_with("_") {
94b46f34 54 return;
abe05a73
XL
55 }
56
57 // Skip anything that looks like `&foo` or `&mut foo`, only look
58 // for by-value bindings
abe05a73
XL
59 let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) {
60 Some(&bm) => bm,
61 None => span_bug!(span, "missing binding mode"),
62 };
63 match bm {
64 ty::BindByValue(hir::MutMutable) => {}
65 _ => return,
66 }
67
94b46f34 68 mutables.entry(name).or_insert(Vec::new()).push((hir_id, span));
abe05a73
XL
69 });
70 }
71
72 for (_name, ids) in mutables {
73 // If any id for this name was used mutably then consider them all
74 // ok, so move on to the next
94b46f34
XL
75 if ids.iter().any(|&(ref hir_id, _)| self.used_mut.contains(hir_id)) {
76 continue;
abe05a73
XL
77 }
78
94b46f34
XL
79 let (hir_id, span) = ids[0];
80 let mut_span = tcx.sess.codemap().span_until_non_whitespace(span);
abe05a73
XL
81
82 // Ok, every name wasn't used mutably, so issue a warning that this
83 // didn't need to be mutable.
94b46f34
XL
84 tcx.struct_span_lint_hir(UNUSED_MUT,
85 hir_id,
86 span,
87 "variable does not need to be mutable")
abe05a73
XL
88 .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
89 .emit();
90 }
91 }
92}
93
94impl<'a, 'tcx> Visitor<'tcx> for UnusedMutCx<'a, 'tcx> {
95 fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
96 NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir)
97 }
98
99 fn visit_arm(&mut self, arm: &hir::Arm) {
100 self.check_unused_mut_pat(&arm.pats)
101 }
102
103 fn visit_local(&mut self, local: &hir::Local) {
ff7c6d11 104 self.check_unused_mut_pat(slice::from_ref(&local.pat));
abe05a73
XL
105 }
106}
107
108impl<'a, 'tcx> Visitor<'tcx> for UsedMutFinder<'a, 'tcx> {
109 fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
110 NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir)
111 }
112
113 fn visit_nested_body(&mut self, id: hir::BodyId) {
114 let def_id = self.bccx.tcx.hir.body_owner_def_id(id);
115 self.set.extend(self.bccx.tcx.borrowck(def_id).used_mut_nodes.iter().cloned());
116 self.visit_body(self.bccx.tcx.hir.body(id));
117 }
118}