]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/used_muts.rs
Auto merge of #55014 - ljedrz:lazyboye_unwraps, r=matthewjasper
[rust.git] / src / librustc_mir / borrow_check / used_muts.rs
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 use rustc::mir::visit::{PlaceContext, Visitor};
12 use rustc::mir::{Local, Location, Place};
13
14 use rustc_data_structures::fx::FxHashSet;
15
16 use borrow_check::MirBorrowckCtxt;
17 use util::collect_writes::is_place_assignment;
18
19 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20     /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
21     /// local variables lint, to update the context's `used_mut` in a single walk.
22     crate fn gather_used_muts(&mut self, locals: FxHashSet<Local>) {
23         let mut visitor = GatherUsedMutsVisitor {
24             needles: locals,
25             mbcx: self,
26         };
27         visitor.visit_mir(visitor.mbcx.mir);
28     }
29 }
30
31 /// MIR visitor gathering the assignments to a set of locals, in a single walk.
32 /// 'visit = the duration of the MIR walk
33 struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
34     needles: FxHashSet<Local>,
35     mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
36 }
37
38 impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
39     fn visit_local(
40         &mut self,
41         local: &Local,
42         place_context: PlaceContext<'tcx>,
43         location: Location,
44     ) {
45         if !self.needles.contains(local) {
46             return;
47         }
48
49         if is_place_assignment(&place_context) {
50             // Propagate the Local assigned at this Location as a used mutable local variable
51             for moi in &self.mbcx.move_data.loc_map[location] {
52                 let mpi = &self.mbcx.move_data.moves[*moi].path;
53                 let path = &self.mbcx.move_data.move_paths[*mpi];
54                 debug!(
55                     "assignment of {:?} to {:?}, adding {:?} to used mutable set",
56                     path.place, local, path.place
57                 );
58                 if let Place::Local(user_local) = path.place {
59                     self.mbcx.used_mut.insert(user_local);
60                 }
61             }
62         }
63     }
64 }