@@ -18,6 +18,7 @@ use rustc_data_structures::graph::dominators::Dominators;
1818use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder } ;
1919use rustc_hir as hir;
2020use rustc_hir:: { def_id:: DefId , HirId , Node } ;
21+ use rustc_index:: bit_set:: BitSet ;
2122use rustc_index:: vec:: IndexVec ;
2223
2324use smallvec:: SmallVec ;
@@ -30,7 +31,9 @@ use rustc_span::{Span, DUMMY_SP};
3031use syntax:: ast:: Name ;
3132
3233use crate :: dataflow;
33- use crate :: dataflow:: generic:: ResultsCursor ;
34+ use crate :: dataflow:: generic:: visitor:: {
35+ visit_results, BorrowckAnalyses , BorrowckResults , ResultsVisitable , ResultsVisitor ,
36+ } ;
3437use crate :: dataflow:: indexes:: { BorrowIndex , InitIndex , MoveOutIndex , MovePathIndex } ;
3538use crate :: dataflow:: move_paths:: { InitLocation , LookupResult , MoveData , MoveError , MovePath } ;
3639use crate :: dataflow:: Borrows ;
@@ -40,7 +43,6 @@ use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
4043use crate :: transform:: MirSource ;
4144
4245use self :: diagnostics:: { AccessKind , RegionName } ;
43- use self :: flows:: Flows ;
4446use self :: location:: LocationTable ;
4547use self :: prefixes:: PrefixSet ;
4648use self :: MutateMode :: { JustWrite , WriteAndRead } ;
@@ -195,7 +197,7 @@ fn do_mir_borrowck<'a, 'tcx>(
195197 Rc :: new ( BorrowSet :: build ( tcx, body, locals_are_invalidated_at_exit, & mdpe. move_data ) ) ;
196198
197199 // Compute non-lexical lifetimes.
198- let nll:: NllOutput { regioncx, polonius_output, opt_closure_req, nll_errors } =
200+ let nll:: NllOutput { regioncx, polonius_output : _ , opt_closure_req, nll_errors } =
199201 nll:: compute_regions (
200202 infcx,
201203 def_id,
@@ -226,17 +228,14 @@ fn do_mir_borrowck<'a, 'tcx>(
226228
227229 let flow_borrows = Borrows :: new ( tcx, & body, regioncx. clone ( ) , & borrow_set) ;
228230 let flow_borrows = dataflow:: generic:: Engine :: new_gen_kill ( tcx, & body, def_id, flow_borrows)
229- . iterate_to_fixpoint ( )
230- . into_cursor ( & body) ;
231+ . iterate_to_fixpoint ( ) ;
231232 let flow_uninits = MaybeUninitializedPlaces :: new ( tcx, & body, & mdpe) ;
232233 let flow_uninits = dataflow:: generic:: Engine :: new_gen_kill ( tcx, & body, def_id, flow_uninits)
233- . iterate_to_fixpoint ( )
234- . into_cursor ( & body) ;
234+ . iterate_to_fixpoint ( ) ;
235235 let flow_ever_inits = EverInitializedPlaces :: new ( tcx, & body, & mdpe) ;
236236 let flow_ever_inits =
237237 dataflow:: generic:: Engine :: new_gen_kill ( tcx, & body, def_id, flow_ever_inits)
238- . iterate_to_fixpoint ( )
239- . into_cursor ( & body) ;
238+ . iterate_to_fixpoint ( ) ;
240239
241240 let movable_generator = match tcx. hir ( ) . get ( id) {
242241 Node :: Expr ( & hir:: Expr {
@@ -276,28 +275,22 @@ fn do_mir_borrowck<'a, 'tcx>(
276275 // Compute and report region errors, if any.
277276 mbcx. report_region_errors ( nll_errors) ;
278277
279- let mut state = Flows :: new ( flow_borrows, flow_uninits, flow_ever_inits, polonius_output) ;
278+ let results = BorrowckAnalyses {
279+ ever_inits : flow_ever_inits,
280+ uninits : flow_uninits,
281+ borrows : flow_borrows,
282+ } ;
280283
281284 if let Some ( errors) = move_errors {
282285 mbcx. report_move_errors ( errors) ;
283286 }
284287
285- // FIXME: refactor into visitor
286- for ( block, block_data) in traversal:: reverse_postorder ( * body) {
287- for ( statement_index, stmt) in block_data. statements . iter ( ) . enumerate ( ) {
288- let loc = Location { block, statement_index } ;
289- state. borrows . seek_before ( loc) ;
290- state. uninits . seek_before ( loc) ;
291- state. ever_inits . seek_before ( loc) ;
292- mbcx. visit_statement_entry ( loc, & stmt, & mut state) ;
293- }
294-
295- let loc = body. terminator_loc ( block) ;
296- state. borrows . seek_before ( loc) ;
297- state. uninits . seek_before ( loc) ;
298- state. ever_inits . seek_before ( loc) ;
299- mbcx. visit_terminator_entry ( loc, block_data. terminator ( ) , & mut state) ;
300- }
288+ visit_results (
289+ & * body,
290+ traversal:: reverse_postorder ( & * body) . map ( |( bb, _) | bb) ,
291+ & results,
292+ & mut mbcx,
293+ ) ;
301294
302295 // Convert any reservation warnings into lints.
303296 let reservation_warnings = mem:: take ( & mut mbcx. reservation_warnings ) ;
@@ -495,23 +488,23 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
495488 next_region_name : RefCell < usize > ,
496489}
497490
491+ type Flows < ' mir , ' tcx > = <BorrowckResults < ' mir , ' tcx > as ResultsVisitable < ' tcx > >:: FlowState ;
492+
498493// Check that:
499494// 1. assignments are always made to mutable locations (FIXME: does that still really go here?)
500495// 2. loans made in overlapping scopes do not conflict
501496// 3. assignments do not affect things loaned out as immutable
502497// 4. moves do not affect things loaned out in any way
503- impl < ' cx , ' tcx > MirBorrowckCtxt < ' cx , ' tcx > {
504- fn body ( & self ) -> & ' cx Body < ' tcx > {
505- * self . body
506- }
498+ impl < ' cx , ' tcx > ResultsVisitor < ' cx , ' tcx > for MirBorrowckCtxt < ' cx , ' tcx > {
499+ type FlowState = Flows < ' cx , ' tcx > ;
507500
508- fn visit_statement_entry (
501+ fn visit_statement (
509502 & mut self ,
510- location : Location ,
503+ flow_state : & Flows < ' cx , ' tcx > ,
511504 stmt : & ' cx Statement < ' tcx > ,
512- flow_state : & mut Flows < ' cx , ' tcx > ,
505+ location : Location ,
513506 ) {
514- debug ! ( "MirBorrowckCtxt::process_statement({:?}, {:?}): {}" , location, stmt, flow_state) ;
507+ debug ! ( "MirBorrowckCtxt::process_statement({:?}, {:?}): {:? }" , location, stmt, flow_state) ;
515508 let span = stmt. source_info . span ;
516509
517510 self . check_activations ( location, span, flow_state) ;
@@ -594,13 +587,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
594587 }
595588 }
596589
597- fn visit_terminator_entry (
590+ fn visit_terminator (
598591 & mut self ,
599- loc : Location ,
592+ flow_state : & Flows < ' cx , ' tcx > ,
600593 term : & ' cx Terminator < ' tcx > ,
601- flow_state : & mut Flows < ' cx , ' tcx > ,
594+ loc : Location ,
602595 ) {
603- debug ! ( "MirBorrowckCtxt::process_terminator({:?}, {:?}): {}" , loc, term, flow_state) ;
596+ debug ! ( "MirBorrowckCtxt::process_terminator({:?}, {:?}): {:? }" , loc, term, flow_state) ;
604597 let span = term. source_info . span ;
605598
606599 self . check_activations ( loc, span, flow_state) ;
@@ -672,18 +665,36 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
672665
673666 TerminatorKind :: Yield { ref value, resume : _, drop : _ } => {
674667 self . consume_operand ( loc, ( value, span) , flow_state) ;
668+ }
669+
670+ TerminatorKind :: Goto { target : _ }
671+ | TerminatorKind :: Abort
672+ | TerminatorKind :: Unreachable
673+ | TerminatorKind :: Resume
674+ | TerminatorKind :: Return
675+ | TerminatorKind :: GeneratorDrop
676+ | TerminatorKind :: FalseEdges { real_target : _, imaginary_target : _ }
677+ | TerminatorKind :: FalseUnwind { real_target : _, unwind : _ } => {
678+ // no data used, thus irrelevant to borrowck
679+ }
680+ }
681+ }
675682
676- if self . movable_generator {
677- // Look for any active borrows to locals
678- let borrow_set = self . borrow_set . clone ( ) ;
683+ fn visit_terminator_exit (
684+ & mut self ,
685+ flow_state : & Flows < ' cx , ' tcx > ,
686+ term : & ' cx Terminator < ' tcx > ,
687+ loc : Location ,
688+ ) {
689+ let span = term. source_info . span ;
679690
680- // FIXME: Don't call `seek_after` manually, instead use a visitor that visits
681- // the exit of a basic block.
682- flow_state . borrows . seek_after ( loc ) ;
683- for i in flow_state . borrows . get ( ) . iter ( ) {
684- let borrow = & borrow_set [ i ] ;
685- self . check_for_local_borrow ( borrow, span ) ;
686- }
691+ match term . kind {
692+ TerminatorKind :: Yield { value : _ , resume : _ , drop : _ } if self . movable_generator => {
693+ // Look for any active borrows to locals
694+ let borrow_set = self . borrow_set . clone ( ) ;
695+ for i in flow_state . borrows . iter ( ) {
696+ let borrow = & borrow_set [ i ] ;
697+ self . check_for_local_borrow ( borrow , span ) ;
687698 }
688699 }
689700
@@ -693,22 +704,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
693704 // StorageDead, but we don't always emit those (notably on unwind paths),
694705 // so this "extra check" serves as a kind of backup.
695706 let borrow_set = self . borrow_set . clone ( ) ;
696-
697- // FIXME: Don't call `seek_after` manually, instead use a visitor that visits
698- // the exit of a basic block.
699- flow_state. borrows . seek_after ( loc) ;
700- for i in flow_state. borrows . get ( ) . iter ( ) {
707+ for i in flow_state. borrows . iter ( ) {
701708 let borrow = & borrow_set[ i] ;
702709 self . check_for_invalidation_at_exit ( loc, borrow, span) ;
703710 }
704711 }
705- TerminatorKind :: Goto { target : _ }
706- | TerminatorKind :: Abort
707- | TerminatorKind :: Unreachable
708- | TerminatorKind :: FalseEdges { real_target : _, imaginary_target : _ }
709- | TerminatorKind :: FalseUnwind { real_target : _, unwind : _ } => {
710- // no data used, thus irrelevant to borrowck
711- }
712+
713+ _ => { }
712714 }
713715 }
714716}
@@ -843,6 +845,10 @@ impl InitializationRequiringAction {
843845}
844846
845847impl < ' cx , ' tcx > MirBorrowckCtxt < ' cx , ' tcx > {
848+ fn body ( & self ) -> & ' cx Body < ' tcx > {
849+ * self . body
850+ }
851+
846852 /// Checks an access to the given place to see if it is allowed. Examines the set of borrows
847853 /// that are in scope, as well as which paths have been initialized, to ensure that (a) the
848854 /// place is initialized and (b) it is not borrowed in some way that would prevent this
@@ -922,7 +928,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
922928 let tcx = self . infcx . tcx ;
923929 let body = self . body ;
924930 let body: & Body < ' _ > = & body;
925- let location_table = self . location_table . start_index ( location) ;
931+ let _location_table = self . location_table . start_index ( location) ;
926932 let borrow_set = self . borrow_set . clone ( ) ;
927933 each_borrow_involving_path (
928934 self ,
@@ -931,7 +937,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
931937 location,
932938 ( sd, place_span. 0 ) ,
933939 & borrow_set,
934- flow_state. borrows_in_scope ( location_table) ,
940+ // flow_state.borrows_in_scope(location_table),
941+ flow_state. borrows . iter ( ) ,
935942 |this, borrow_index, borrow| match ( rw, borrow. kind ) {
936943 // Obviously an activation is compatible with its own
937944 // reservation (or even prior activating uses of same
@@ -1553,7 +1560,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15531560 location : Location ,
15541561 desired_action : InitializationRequiringAction ,
15551562 place_span : ( PlaceRef < ' cx , ' tcx > , Span ) ,
1556- maybe_uninits : & ResultsCursor < ' cx , ' tcx , MaybeUninitializedPlaces < ' cx , ' tcx > > ,
1563+ maybe_uninits : & BitSet < MovePathIndex > ,
15571564 from : u32 ,
15581565 to : u32 ,
15591566 ) {
0 commit comments