Skip to content

Commit 737c5cc

Browse files
committed
Auto merge of #51660 - lqd:the-MIRnistry-of-walks, r=<try>
NLL: Walk the MIR only once for the "unused mut" lint Turns the quadratic loop gathering local variable assignments into a single MIR walk, and brings down the number of `super_mir` calls generated from `do_mir_borrowck` to the expected levels seen in `nll::replace_regions_in_mir` and `nll::compute_regions`, i.e. on clap: 1883 `super_mir` calls instead of 8011. The limited perf numbers I could gather on my machines look to be what we expected: `clap-check` seems to be gaining back a lot of the 7% we previously saw in `visit_mir`. Fixes #51641. r? @nikomatsakis
2 parents 637fd2e + 7154383 commit 737c5cc

File tree

2 files changed

+77
-14
lines changed

2 files changed

+77
-14
lines changed

src/librustc_mir/borrow_check/mod.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ mod location;
6161
crate mod place_ext;
6262
mod prefixes;
6363
mod path_utils;
64+
mod used_muts;
6465

6566
pub(crate) mod nll;
6667

@@ -281,20 +282,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
281282
.filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
282283
.cloned()
283284
.collect();
284-
285-
for local in temporary_used_locals {
286-
for location in mbcx.mir.find_assignments(local) {
287-
for moi in &mbcx.move_data.loc_map[location] {
288-
let mpi = &mbcx.move_data.moves[*moi].path;
289-
let path = &mbcx.move_data.move_paths[*mpi];
290-
debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set",
291-
path.place, local, path.place);
292-
if let Place::Local(user_local) = path.place {
293-
mbcx.used_mut.insert(user_local);
294-
}
295-
}
296-
}
297-
}
285+
mbcx.gather_used_muts(temporary_used_locals);
298286

299287
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
300288

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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+
18+
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
19+
/// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
20+
/// local variables lint, to update the context's `used_mut` in a single walk.
21+
crate fn gather_used_muts(&mut self, locals: FxHashSet<Local>) {
22+
let mut visitor = GatherUsedMutsVisitor {
23+
needles: locals,
24+
mbcx: self,
25+
};
26+
visitor.visit_mir(visitor.mbcx.mir);
27+
}
28+
}
29+
30+
/// MIR visitor gathering the assignments to a set of locals, in a single walk.
31+
/// 'visit = the duration of the MIR walk
32+
struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
33+
needles: FxHashSet<Local>,
34+
mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
35+
}
36+
37+
impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
38+
fn visit_local(
39+
&mut self,
40+
local: &Local,
41+
place_context: PlaceContext<'tcx>,
42+
location: Location,
43+
) {
44+
if !self.needles.contains(local) {
45+
return;
46+
}
47+
48+
match place_context {
49+
PlaceContext::Store | PlaceContext::Call => {
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+
PlaceContext::AsmOutput
64+
| PlaceContext::Drop
65+
| PlaceContext::Inspect
66+
| PlaceContext::Borrow { .. }
67+
| PlaceContext::Projection(..)
68+
| PlaceContext::Copy
69+
| PlaceContext::Move
70+
| PlaceContext::StorageLive
71+
| PlaceContext::StorageDead
72+
| PlaceContext::Validate => {}
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)