]> git.lizzy.rs Git - rust.git/commitdiff
NLL: Walk the MIR only once for the "unused mut" lint
authorRémy Rakic <remy.rakic@gmail.com>
Wed, 20 Jun 2018 16:02:44 +0000 (18:02 +0200)
committerRémy Rakic <remy.rakic@gmail.com>
Wed, 20 Jun 2018 16:02:44 +0000 (18:02 +0200)
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/used_muts.rs [new file with mode: 0644]

index 3d3275a6b171485ae18cbd47e75ef9a69f16b782..115f36c149b64907ce33fa3974f5c9088803efbf 100644 (file)
@@ -61,6 +61,7 @@
 crate mod place_ext;
 mod prefixes;
 mod path_utils;
+mod used_muts;
 
 pub(crate) mod nll;
 
@@ -281,20 +282,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
             .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
             .cloned()
             .collect();
-
-    for local in temporary_used_locals {
-        for location in mbcx.mir.find_assignments(local) {
-            for moi in &mbcx.move_data.loc_map[location] {
-                let mpi = &mbcx.move_data.moves[*moi].path;
-                let path = &mbcx.move_data.move_paths[*mpi];
-                debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set",
-                       path.place, local, path.place);
-                if let Place::Local(user_local) = path.place {
-                    mbcx.used_mut.insert(user_local);
-                }
-            }
-        }
-    }
+    mbcx.gather_used_muts(temporary_used_locals);
 
     debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
 
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
new file mode 100644 (file)
index 0000000..0a6258c
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2018 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::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::{Local, Location, Place};
+
+use rustc_data_structures::fx::FxHashSet;
+
+use borrow_check::MirBorrowckCtxt;
+
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
+    /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
+    /// local variables lint, to update the context's `used_mut` in a single walk.
+    crate fn gather_used_muts(&mut self, locals: FxHashSet<Local>) {
+        let mut visitor = GatherUsedMutsVisitor {
+            needles: locals,
+            mbcx: self,
+        };
+        visitor.visit_mir(visitor.mbcx.mir);
+    }
+}
+
+/// MIR visitor gathering the assignments to a set of locals, in a single walk.
+/// 'visit = the duration of the MIR walk
+struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
+    needles: FxHashSet<Local>,
+    mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+}
+
+impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
+    fn visit_local(
+        &mut self,
+        local: &Local,
+        place_context: PlaceContext<'tcx>,
+        location: Location,
+    ) {
+        if !self.needles.contains(local) {
+            return;
+        }
+
+        match place_context {
+            PlaceContext::Store | PlaceContext::Call => {
+                // Propagate the Local assigned at this Location as a used mutable local variable
+                for moi in &self.mbcx.move_data.loc_map[location] {
+                    let mpi = &self.mbcx.move_data.moves[*moi].path;
+                    let path = &self.mbcx.move_data.move_paths[*mpi];
+                    debug!(
+                        "assignment of {:?} to {:?}, adding {:?} to used mutable set",
+                        path.place, local, path.place
+                    );
+                    if let Place::Local(user_local) = path.place {
+                        self.mbcx.used_mut.insert(user_local);
+                    }
+                }
+            }
+            PlaceContext::AsmOutput
+            | PlaceContext::Drop
+            | PlaceContext::Inspect
+            | PlaceContext::Borrow { .. }
+            | PlaceContext::Projection(..)
+            | PlaceContext::Copy
+            | PlaceContext::Move
+            | PlaceContext::StorageLive
+            | PlaceContext::StorageDead
+            | PlaceContext::Validate => {}
+        }
+    }
+}