Skip to content

Commit 373fc93

Browse files
committed
Make move out computation lazy
1 parent 685fb54 commit 373fc93

File tree

7 files changed

+110
-189
lines changed

7 files changed

+110
-189
lines changed

src/librustc/mir/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,28 @@ impl<'tcx> Mir<'tcx> {
203203
ReadGuard::map(self.predecessors(), |p| &p[bb])
204204
}
205205

206+
#[inline]
207+
pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
208+
let if_zero_locations = if loc.statement_index == 0 {
209+
let predecessor_blocks = self.predecessors_for(loc.block);
210+
let num_predecessor_blocks = predecessor_blocks.len();
211+
Some((0 .. num_predecessor_blocks)
212+
.map(move |i| predecessor_blocks[i])
213+
.map(move |bb| self.terminator_loc(bb))
214+
)
215+
} else {
216+
None
217+
};
218+
219+
let if_not_zero_locations = if loc.statement_index == 0 {
220+
None
221+
} else {
222+
Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
223+
};
224+
225+
if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
226+
}
227+
206228
#[inline]
207229
pub fn dominators(&self) -> Dominators<BasicBlock> {
208230
dominators(self)

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local};
1515
use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
1616
use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
1717
use rustc::ty;
18+
use rustc_data_structures::fx::FxHashSet;
1819
use rustc_data_structures::indexed_vec::Idx;
1920
use rustc_data_structures::sync::Lrc;
2021
use rustc_errors::DiagnosticBuilder;
@@ -24,8 +25,9 @@ use super::borrow_set::BorrowData;
2425
use super::{Context, MirBorrowckCtxt};
2526
use super::{InitializationRequiringAction, PrefixSet};
2627

28+
use dataflow::drop_flag_effects;
2729
use dataflow::move_paths::MovePathIndex;
28-
use dataflow::{FlowAtLocation, MovingOutStatements};
30+
use dataflow::move_paths::indexes::MoveOutIndex;
2931
use util::borrowck_errors::{BorrowckErrors, Origin};
3032

3133
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
@@ -35,17 +37,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
3537
desired_action: InitializationRequiringAction,
3638
(place, span): (&Place<'tcx>, Span),
3739
mpi: MovePathIndex,
38-
curr_move_out: &FlowAtLocation<MovingOutStatements<'_, 'gcx, 'tcx>>,
3940
) {
4041
let use_spans = self
4142
.move_spans(place, context.loc)
4243
.or_else(|| self.borrow_spans(span, context.loc));
4344
let span = use_spans.args_or_use();
4445

45-
let mois = self.move_data.path_map[mpi]
46-
.iter()
47-
.filter(|moi| curr_move_out.contains(moi))
48-
.collect::<Vec<_>>();
46+
let mois = self.get_moved_indexes(context, mpi);
47+
debug!("report_use_of_moved_or_uninitialized: mois={:?}", mois);
4948

5049
if mois.is_empty() {
5150
let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();
@@ -93,7 +92,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
9392

9493
let mut is_loop_move = false;
9594
for moi in &mois {
96-
let move_out = self.move_data.moves[**moi];
95+
let move_out = self.move_data.moves[*moi];
9796
let moved_place = &self.move_data.move_paths[move_out.path].place;
9897

9998
let move_spans = self.move_spans(moved_place, move_out.source);
@@ -148,7 +147,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
148147
};
149148

150149
if needs_note {
151-
let mpi = self.move_data.moves[*mois[0]].path;
150+
let mpi = self.move_data.moves[mois[0]].path;
152151
let place = &self.move_data.move_paths[mpi].place;
153152

154153
if let Some(ty) = self.retrieve_type_for_place(place) {
@@ -521,6 +520,81 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
521520
err
522521
}
523522

523+
fn get_moved_indexes(
524+
&mut self,
525+
context: Context,
526+
mpi: MovePathIndex,
527+
) -> Vec<MoveOutIndex> {
528+
let mir = self.mir;
529+
530+
let mut stack = Vec::new();
531+
stack.extend(mir.predecessor_locations(context.loc));
532+
533+
let mut visited = FxHashSet();
534+
let mut result = vec![];
535+
536+
'dfs:
537+
while let Some(l) = stack.pop() {
538+
debug!("report_use_of_moved_or_uninitialized: current_location={:?}", l);
539+
540+
if !visited.insert(l) {
541+
continue;
542+
}
543+
544+
// check for moves
545+
let stmt_kind = mir[l.block].statements.get(l.statement_index).map(|s| &s.kind);
546+
if let Some(StatementKind::StorageDead(..)) = stmt_kind {
547+
// this analysis only tries to find moves explicitly
548+
// written by the user, so we ignore the move-outs
549+
// created by `StorageDead` and at the beginning
550+
// of a function.
551+
} else {
552+
for moi in &self.move_data.loc_map[l] {
553+
debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
554+
if self.move_data.moves[*moi].path == mpi {
555+
debug!("report_use_of_moved_or_uninitialized: found");
556+
result.push(*moi);
557+
558+
// Strictly speaking, we could continue our DFS here. There may be
559+
// other moves that can reach the point of error. But it is kind of
560+
// confusing to highlight them.
561+
//
562+
// Example:
563+
//
564+
// ```
565+
// let a = vec![];
566+
// let b = a;
567+
// let c = a;
568+
// drop(a); // <-- current point of error
569+
// ```
570+
//
571+
// Because we stop the DFS here, we only highlight `let c = a`,
572+
// and not `let b = a`. We will of course also report an error at
573+
// `let c = a` which highlights `let b = a` as the move.
574+
continue 'dfs;
575+
}
576+
}
577+
}
578+
579+
// check for inits
580+
let mut any_match = false;
581+
drop_flag_effects::for_location_inits(
582+
self.tcx,
583+
self.mir,
584+
self.move_data,
585+
l,
586+
|m| if m == mpi { any_match = true; },
587+
);
588+
if any_match {
589+
continue 'dfs;
590+
}
591+
592+
stack.extend(mir.predecessor_locations(l));
593+
}
594+
595+
result
596+
}
597+
524598
pub(super) fn report_illegal_mutation_of_borrowed(
525599
&mut self,
526600
context: Context,

src/librustc_mir/borrow_check/flows.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use polonius_engine::Output;
2424
use dataflow::move_paths::indexes::BorrowIndex;
2525
use dataflow::move_paths::HasMoveData;
2626
use dataflow::Borrows;
27-
use dataflow::{EverInitializedPlaces, MovingOutStatements};
27+
use dataflow::EverInitializedPlaces;
2828
use dataflow::{FlowAtLocation, FlowsAtLocation};
2929
use dataflow::MaybeUninitializedPlaces;
3030
use either::Either;
@@ -35,7 +35,6 @@ use std::rc::Rc;
3535
crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
3636
borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
3737
pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
38-
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
3938
pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
4039

4140
/// Polonius Output
@@ -46,14 +45,12 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
4645
crate fn new(
4746
borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
4847
uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
49-
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
5048
ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
5149
polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
5250
) -> Self {
5351
Flows {
5452
borrows,
5553
uninits,
56-
move_outs,
5754
ever_inits,
5855
polonius_output,
5956
}
@@ -79,7 +76,6 @@ macro_rules! each_flow {
7976
($this:ident, $meth:ident($arg:ident)) => {
8077
FlowAtLocation::$meth(&mut $this.borrows, $arg);
8178
FlowAtLocation::$meth(&mut $this.uninits, $arg);
82-
FlowAtLocation::$meth(&mut $this.move_outs, $arg);
8379
FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
8480
};
8581
}
@@ -146,18 +142,6 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
146142
});
147143
s.push_str("] ");
148144

149-
s.push_str("move_out: [");
150-
let mut saw_one = false;
151-
self.move_outs.each_state_bit(|mpi_move_out| {
152-
if saw_one {
153-
s.push_str(", ");
154-
};
155-
saw_one = true;
156-
let move_out = &self.move_outs.operator().move_data().moves[mpi_move_out];
157-
s.push_str(&format!("{:?}", move_out));
158-
});
159-
s.push_str("] ");
160-
161145
s.push_str("ever_init: [");
162146
let mut saw_one = false;
163147
self.ever_inits.each_state_bit(|mpi_ever_init| {

src/librustc_mir/borrow_check/mod.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use dataflow::DataflowResultsConsumer;
4343
use dataflow::FlowAtLocation;
4444
use dataflow::MoveDataParamEnv;
4545
use dataflow::{do_dataflow, DebugFormatted};
46-
use dataflow::{EverInitializedPlaces, MovingOutStatements};
46+
use dataflow::EverInitializedPlaces;
4747
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
4848
use util::borrowck_errors::{BorrowckErrors, Origin};
4949

@@ -186,15 +186,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
186186
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
187187
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
188188
));
189-
let flow_move_outs = FlowAtLocation::new(do_dataflow(
190-
tcx,
191-
mir,
192-
id,
193-
&attributes,
194-
&dead_unwinds,
195-
MovingOutStatements::new(tcx, mir, &mdpe),
196-
|bd, i| DebugFormatted::new(&bd.move_data().moves[i]),
197-
));
198189
let flow_ever_inits = FlowAtLocation::new(do_dataflow(
199190
tcx,
200191
mir,
@@ -268,7 +259,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
268259
let mut state = Flows::new(
269260
flow_borrows,
270261
flow_uninits,
271-
flow_move_outs,
272262
flow_ever_inits,
273263
polonius_output,
274264
);
@@ -1617,7 +1607,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16171607
let place = self.base_path(place_span.0);
16181608

16191609
let maybe_uninits = &flow_state.uninits;
1620-
let curr_move_outs = &flow_state.move_outs;
16211610

16221611
// Bad scenarios:
16231612
//
@@ -1663,7 +1652,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16631652
desired_action,
16641653
place_span,
16651654
mpi,
1666-
curr_move_outs,
16671655
);
16681656
return; // don't bother finding other problems.
16691657
}
@@ -1691,7 +1679,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16911679
let place = self.base_path(place_span.0);
16921680

16931681
let maybe_uninits = &flow_state.uninits;
1694-
let curr_move_outs = &flow_state.move_outs;
16951682

16961683
// Bad scenarios:
16971684
//
@@ -1727,7 +1714,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
17271714
desired_action,
17281715
place_span,
17291716
child_mpi,
1730-
curr_move_outs,
17311717
);
17321718
return; // don't bother finding other problems.
17331719
}

0 commit comments

Comments
 (0)