]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #45283 - alexcrichton:used-mut-nodes, r=arielb1
authorbors <bors@rust-lang.org>
Mon, 16 Oct 2017 03:02:05 +0000 (03:02 +0000)
committerbors <bors@rust-lang.org>
Mon, 16 Oct 2017 03:02:05 +0000 (03:02 +0000)
rustc: Remove `used_mut_nodes` from `TyCtxt`

This updates the borrowck query to return a result, and this result is then used
to incrementally check for unused mutable nodes given sets of all the used
mutable nodes.

Closes #42384

16 files changed:
src/Cargo.lock
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/middle/borrowck.rs [new file with mode: 0644]
src/librustc/ty/context.rs
src/librustc/ty/maps/mod.rs
src/librustc_borrowck/Cargo.toml
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/unused.rs [new file with mode: 0644]
src/librustc_borrowck/lib.rs
src/librustc_lint/Cargo.toml
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/test/ui/lint/suggestions.stderr

index 2b95be27ffea7513dca5c794992931dc07da06ce..328ce353e2a139351cf0c4ab75b55c0b9dc0eaa0 100644 (file)
@@ -1504,6 +1504,7 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc_back 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_mir 0.0.0",
  "syntax 0.0.0",
@@ -1611,7 +1612,6 @@ version = "0.0.0"
 dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_back 0.0.0",
  "rustc_const_eval 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
index 015dbbb7affa952e6dd5be9e706d6a397876881f..ed440849b4826c7c2111b296ec84367f257aa74e 100644 (file)
 
 pub mod middle {
     pub mod allocator;
+    pub mod borrowck;
     pub mod expr_use_visitor;
     pub mod const_val;
     pub mod cstore;
index 5fe75d8ca71e38df9b8a2cd1c54665679d5775b6..d28963fc726abf5b6ffd9b89845d27dc12fdbeb3 100644 (file)
     "unnecessary use of an `unsafe` block"
 }
 
+declare_lint! {
+    pub UNUSED_MUT,
+    Warn,
+    "detect mut variables which don't need to be mutable"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -263,7 +269,8 @@ fn get_lints(&self) -> LintArray {
             PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
             LATE_BOUND_LIFETIME_ARGUMENTS,
             DEPRECATED,
-            UNUSED_UNSAFE
+            UNUSED_UNSAFE,
+            UNUSED_MUT
         )
     }
 }
diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs
new file mode 100644 (file)
index 0000000..c869042
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ich::StableHashingContext;
+use hir::HirId;
+use util::nodemap::FxHashSet;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHasherResult};
+
+pub struct BorrowCheckResult {
+    pub used_mut_nodes: FxHashSet<HirId>,
+}
+
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for BorrowCheckResult {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let BorrowCheckResult {
+            ref used_mut_nodes,
+        } = *self;
+        used_mut_nodes.hash_stable(hcx, hasher);
+    }
+}
index 740299b91f118d6b24810704a327928bab862c64..24ba38cf147796449be3a2883fba992892a54fff 100644 (file)
@@ -898,11 +898,6 @@ pub struct GlobalCtxt<'tcx> {
 
     pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>,
 
-    /// Set of nodes which mark locals as mutable which end up getting used at
-    /// some point. Local variable definitions not in this set can be warned
-    /// about.
-    pub used_mut_nodes: RefCell<NodeSet>,
-
     /// Caches the results of trait selection. This cache is used
     /// for things that do not have to do with the parameters in scope.
     pub selection_cache: traits::SelectionCache<'tcx>,
@@ -1185,7 +1180,6 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             rcache: RefCell::new(FxHashMap()),
             normalized_cache: RefCell::new(FxHashMap()),
             inhabitedness_cache: RefCell::new(FxHashMap()),
-            used_mut_nodes: RefCell::new(NodeSet()),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             rvalue_promotable_to_static: RefCell::new(NodeMap()),
index 4b68f5addd2be3c7d4d700d4774231f863b9a42b..58405c261ad7239f73e4bef519aabbc78face5ba 100644 (file)
@@ -15,6 +15,7 @@
 use hir::{self, TraitCandidate, ItemLocalId};
 use hir::svh::Svh;
 use lint;
+use middle::borrowck::BorrowCheckResult;
 use middle::const_val;
 use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary,
                      ExternBodyNestedBodies};
 
     [] fn coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
 
-    [] fn borrowck: BorrowCheck(DefId) -> (),
+    [] fn borrowck: BorrowCheck(DefId) -> Rc<BorrowCheckResult>,
     // FIXME: shouldn't this return a `Result<(), BorrowckErrors>` instead?
     [] fn mir_borrowck: MirBorrowCheck(DefId) -> (),
 
index 25f02537490fa8d694a52ff0a366692622c54d45..4c09a9e003ddb8645645d717ce53a5e9cd53dd15 100644 (file)
@@ -15,5 +15,6 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 graphviz = { path = "../libgraphviz" }
 rustc = { path = "../librustc" }
+rustc_back = { path = "../librustc_back" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_errors = { path = "../librustc_errors" }
index fea662e21fa9f386fc497c4a983ba029abcd3afa..6ce5afd4bf15f97c81d3a60b41c15e8ba47483ef 100644 (file)
@@ -770,7 +770,8 @@ fn check_assignment(&self,
             let lp = opt_loan_path(&assignee_cmt).unwrap();
             self.move_data.each_assignment_of(assignment_id, &lp, |assign| {
                 if assignee_cmt.mutbl.is_mutable() {
-                    self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
+                    let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id);
+                    self.bccx.used_mut_nodes.borrow_mut().insert(hir_id);
                 } else {
                     self.bccx.report_reassigned_immutable_variable(
                         assignment_span,
index a58b62ba2a7092351bda2deb4daaf6b9caef79be..1827ddabe4e2a9d6c7f46e695a96f99166ddbafe 100644 (file)
@@ -442,13 +442,13 @@ pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
             wrapped_path = match current_path.kind {
                 LpVar(local_id) => {
                     if !through_borrow {
-                        self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
+                        let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id);
+                        self.bccx.used_mut_nodes.borrow_mut().insert(hir_id);
                     }
                     None
                 }
                 LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => {
-                    let local_id = self.tcx().hir.hir_to_node_id(var_id);
-                    self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
+                    self.bccx.used_mut_nodes.borrow_mut().insert(var_id);
                     None
                 }
                 LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) |
index fc3c2a3f68fedfcfaec97f3f7b21ee7e284312d7..d29250ac57cfbeb10e9450046ab28aaf852912fd 100644 (file)
@@ -20,6 +20,7 @@
 
 use self::InteriorKind::*;
 
+use rustc::hir::HirId;
 use rustc::hir::map as hir_map;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::cfg;
@@ -27,6 +28,7 @@
 use rustc::middle::dataflow::BitwiseOperator;
 use rustc::middle::dataflow::DataFlowOperator;
 use rustc::middle::dataflow::KillFrom;
+use rustc::middle::borrowck::BorrowCheckResult;
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
@@ -37,7 +39,9 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
+use rustc::util::nodemap::FxHashSet;
 
+use std::cell::RefCell;
 use std::fmt;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
@@ -54,6 +58,8 @@
 
 pub mod move_data;
 
+mod unused;
+
 #[derive(Clone, Copy)]
 pub struct LoanDataFlowOperator;
 
@@ -79,7 +85,9 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
     pub move_data: move_data::FlowedMoveData<'a, 'tcx>,
 }
 
-fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
+fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
+    -> Rc<BorrowCheckResult>
+{
     debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
 
     let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap();
@@ -91,7 +99,9 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
             // those things (notably the synthesized constructors from
             // tuple structs/variants) do not have an associated body
             // and do not need borrowchecking.
-            return;
+            return Rc::new(BorrowCheckResult {
+                used_mut_nodes: FxHashSet(),
+            })
         }
         _ => { }
     }
@@ -100,7 +110,14 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     let tables = tcx.typeck_tables_of(owner_def_id);
     let region_scope_tree = tcx.region_scope_tree(owner_def_id);
     let body = tcx.hir.body(body_id);
-    let bccx = &mut BorrowckCtxt { tcx, tables, region_scope_tree, owner_def_id, body };
+    let mut bccx = BorrowckCtxt {
+        tcx,
+        tables,
+        region_scope_tree,
+        owner_def_id,
+        body,
+        used_mut_nodes: RefCell::new(FxHashSet()),
+    };
 
     // Eventually, borrowck will always read the MIR, but at the
     // moment we do not. So, for now, we always force MIR to be
@@ -118,14 +135,19 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     if let Some(AnalysisData { all_loans,
                                loans: loan_dfcx,
                                move_data: flowed_moves }) =
-        build_borrowck_dataflow_data(bccx, false, body_id,
+        build_borrowck_dataflow_data(&mut bccx, false, body_id,
                                      |bccx| {
                                          cfg = Some(cfg::CFG::new(bccx.tcx, &body));
                                          cfg.as_mut().unwrap()
                                      })
     {
-        check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
+        check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
     }
+    unused::check(&mut bccx, body);
+
+    Rc::new(BorrowCheckResult {
+        used_mut_nodes: bccx.used_mut_nodes.into_inner(),
+    })
 }
 
 fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tcx>,
@@ -198,7 +220,14 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
     let tables = tcx.typeck_tables_of(owner_def_id);
     let region_scope_tree = tcx.region_scope_tree(owner_def_id);
     let body = tcx.hir.body(body_id);
-    let mut bccx = BorrowckCtxt { tcx, tables, region_scope_tree, owner_def_id, body };
+    let mut bccx = BorrowckCtxt {
+        tcx,
+        tables,
+        region_scope_tree,
+        owner_def_id,
+        body,
+        used_mut_nodes: RefCell::new(FxHashSet()),
+    };
 
     let dataflow_data = build_borrowck_dataflow_data(&mut bccx, true, body_id, |_| cfg);
     (bccx, dataflow_data.unwrap())
@@ -219,6 +248,8 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
     owner_def_id: DefId,
 
     body: &'tcx hir::Body,
+
+    used_mut_nodes: RefCell<FxHashSet<HirId>>,
 }
 
 impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs
new file mode 100644 (file)
index 0000000..228824b
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
+use rustc::hir::{self, HirId};
+use rustc::lint::builtin::UNUSED_MUT;
+use rustc::ty;
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc_back::slice;
+use syntax::ptr::P;
+
+use borrowck::BorrowckCtxt;
+
+pub fn check<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: &'tcx hir::Body) {
+    let mut used_mut = bccx.used_mut_nodes.borrow().clone();
+    UsedMutFinder {
+        bccx,
+        set: &mut used_mut,
+    }.visit_expr(&body.value);
+    let mut cx = UnusedMutCx { bccx, used_mut };
+    for arg in body.arguments.iter() {
+        cx.check_unused_mut_pat(slice::ref_slice(&arg.pat));
+    }
+    cx.visit_expr(&body.value);
+}
+
+struct UsedMutFinder<'a, 'tcx: 'a> {
+    bccx: &'a BorrowckCtxt<'a, 'tcx>,
+    set: &'a mut FxHashSet<HirId>,
+}
+
+struct UnusedMutCx<'a, 'tcx: 'a> {
+    bccx: &'a BorrowckCtxt<'a, 'tcx>,
+    used_mut: FxHashSet<HirId>,
+}
+
+impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> {
+    fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
+        let tcx = self.bccx.tcx;
+        let mut mutables = FxHashMap();
+        for p in pats {
+            p.each_binding(|_, id, span, path1| {
+                let name = path1.node;
+
+                // Skip anything that looks like `_foo`
+                if name.as_str().starts_with("_") {
+                    return
+                }
+
+                // Skip anything that looks like `&foo` or `&mut foo`, only look
+                // for by-value bindings
+                let hir_id = tcx.hir.node_to_hir_id(id);
+                let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) {
+                    Some(&bm) => bm,
+                    None => span_bug!(span, "missing binding mode"),
+                };
+                match bm {
+                    ty::BindByValue(hir::MutMutable) => {}
+                    _ => return,
+                }
+
+                mutables.entry(name).or_insert(Vec::new()).push((id, hir_id, span));
+            });
+        }
+
+        for (_name, ids) in mutables {
+            // If any id for this name was used mutably then consider them all
+            // ok, so move on to the next
+            if ids.iter().any(|&(_, ref id, _)| self.used_mut.contains(id)) {
+                continue
+            }
+
+            let mut_span = tcx.sess.codemap().span_until_char(ids[0].2, ' ');
+
+            // Ok, every name wasn't used mutably, so issue a warning that this
+            // didn't need to be mutable.
+            tcx.struct_span_lint_node(UNUSED_MUT,
+                                      ids[0].0,
+                                      ids[0].2,
+                                      "variable does not need to be mutable")
+                .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
+                .emit();
+        }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for UnusedMutCx<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir)
+    }
+
+    fn visit_arm(&mut self, arm: &hir::Arm) {
+        self.check_unused_mut_pat(&arm.pats)
+    }
+
+    fn visit_local(&mut self, local: &hir::Local) {
+        self.check_unused_mut_pat(slice::ref_slice(&local.pat));
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for UsedMutFinder<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir)
+    }
+
+    fn visit_nested_body(&mut self, id: hir::BodyId) {
+        let def_id = self.bccx.tcx.hir.body_owner_def_id(id);
+        self.set.extend(self.bccx.tcx.borrowck(def_id).used_mut_nodes.iter().cloned());
+        self.visit_body(self.bccx.tcx.hir.body(id));
+    }
+}
index 11120d2e46f2af6ed09d7a316bfeeec19610908c..78aacd49f807dafafc8ae37f7f29db8ed6e81e27 100644 (file)
@@ -21,6 +21,7 @@
 extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
+extern crate rustc_back;
 
 // for "clarity", rename the graphviz crate to dot; graphviz within `borrowck`
 // refers to the borrowck-specific graphviz adapter traits.
index c3c5461ff7c506a612d45564e01aa6b8a8a41938..cebf52d5af7a9c2cf4f2686617bb3e60fdb5f1cd 100644 (file)
@@ -12,7 +12,6 @@ test = false
 [dependencies]
 log = "0.3"
 rustc = { path = "../librustc" }
-rustc_back = { path = "../librustc_back" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index fbf993f45576ceb6f214f719c94dcbff9c281804..4ba7f7aa951f75c50de6c82a5c687a1dbe03f482 100644 (file)
@@ -38,7 +38,6 @@
 extern crate rustc;
 #[macro_use]
 extern crate log;
-extern crate rustc_back;
 extern crate rustc_const_eval;
 extern crate syntax_pos;
 
@@ -129,7 +128,6 @@ macro_rules! add_lint_group {
                  NonUpperCaseGlobals,
                  NonShorthandFieldPatterns,
                  UnsafeCode,
-                 UnusedMut,
                  UnusedAllocation,
                  MissingCopyImplementations,
                  UnstableFeatures,
index e2ade19b6e2856a4f9a6361ad168ff412ea5578e..a058f84e58806da255b7b2ade7159e7263301795 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::ty;
 use rustc::ty::adjustment;
-use util::nodemap::FxHashMap;
 use lint::{LateContext, EarlyContext, LintContext, LintArray};
 use lint::{LintPass, EarlyLintPass, LateLintPass};
 
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-
 use syntax::ast;
 use syntax::attr;
 use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
-use syntax::symbol::keywords;
-use syntax::ptr::P;
 use syntax::print::pprust;
+use syntax::symbol::keywords;
 use syntax::util::parser;
 use syntax_pos::Span;
 
-use rustc_back::slice;
 use rustc::hir;
-use rustc::hir::intravisit::FnKind;
-
-declare_lint! {
-    pub UNUSED_MUT,
-    Warn,
-    "detect mut variables which don't need to be mutable"
-}
-
-#[derive(Copy, Clone)]
-pub struct UnusedMut;
-
-impl UnusedMut {
-    fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
-        // collect all mutable pattern and group their NodeIDs by their Identifier to
-        // avoid false warnings in match arms with multiple patterns
-
-        let mut mutables = FxHashMap();
-        for p in pats {
-            p.each_binding(|_, id, span, path1| {
-                let hir_id = cx.tcx.hir.node_to_hir_id(id);
-                let bm = match cx.tables.pat_binding_modes().get(hir_id) {
-                    Some(&bm) => bm,
-                    None => span_bug!(span, "missing binding mode"),
-                };
-                let name = path1.node;
-                if let ty::BindByValue(hir::MutMutable) = bm {
-                    if !name.as_str().starts_with("_") {
-                        match mutables.entry(name) {
-                            Vacant(entry) => {
-                                entry.insert(vec![id]);
-                            }
-                            Occupied(mut entry) => {
-                                entry.get_mut().push(id);
-                            }
-                        }
-                    }
-                }
-            });
-        }
-
-        let used_mutables = cx.tcx.used_mut_nodes.borrow();
-        for (_, v) in &mutables {
-            if !v.iter().any(|e| used_mutables.contains(e)) {
-                let binding_span = cx.tcx.hir.span(v[0]);
-                let mut_span = cx.tcx.sess.codemap().span_until_char(binding_span, ' ');
-                let mut err = cx.struct_span_lint(UNUSED_MUT,
-                                                  binding_span,
-                                                  "variable does not need to be mutable");
-                err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
-                err.emit();
-            }
-        }
-    }
-}
-
-impl LintPass for UnusedMut {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUT)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedMut {
-    fn check_arm(&mut self, cx: &LateContext, a: &hir::Arm) {
-        self.check_unused_mut_pat(cx, &a.pats)
-    }
-
-    fn check_local(&mut self, cx: &LateContext, l: &hir::Local) {
-        self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
-    }
-
-    fn check_fn(&mut self,
-                cx: &LateContext,
-                _: FnKind,
-                _: &hir::FnDecl,
-                body: &hir::Body,
-                _: Span,
-                _: ast::NodeId) {
-        for a in &body.arguments {
-            self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
-        }
-    }
-}
 
 declare_lint! {
     pub UNUSED_MUST_USE,
index 5b2a4f589f7381c0b15cff47ca8c785ec3aed91e..9a69c52e6cfb45a78be7303a95cac92e33ef9dd2 100644 (file)
@@ -14,6 +14,20 @@ warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was
    |
    = note: #[warn(deprecated)] on by default
 
+warning: variable does not need to be mutable
+  --> $DIR/suggestions.rs:17:13
+   |
+17 |         let mut a = (1); // should suggest no `mut`, no parens
+   |             ---^^
+   |             |
+   |             help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/suggestions.rs:11:9
+   |
+11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
+   |         ^^^^^^^^^^
+
 warning: denote infinite loops with `loop { ... }`
   --> $DIR/suggestions.rs:16:5
    |
@@ -29,17 +43,3 @@ warning: denote infinite loops with `loop { ... }`
    |
    = note: #[warn(while_true)] on by default
 
-warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:17:13
-   |
-17 |         let mut a = (1); // should suggest no `mut`, no parens
-   |             ---^^
-   |             |
-   |             help: remove this `mut`
-   |
-note: lint level defined here
-  --> $DIR/suggestions.rs:11:9
-   |
-11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
-   |         ^^^^^^^^^^
-