Skip to content

Commit 75340f4

Browse files
committed
Revise dataflow to do a cfg-driven walk.
Fix #6298. This is instead of the prior approach of emulating cfg traversal privately by traversing AST in same way). Of special note, this removes a special case handling of `ExprParen` that was actually injecting a bug (since it was acting like an expression like `(*func)()` was consuming `*func` *twice*: once from `(*func)` and again from `*func`). nikomatsakis was the first one to point out that it might suffice to simply have the outer `ExprParen` do the consumption of the contents (alone). (This version has been updated to incorporate feedback from Niko's review of PR 14873.)
1 parent fef63e2 commit 75340f4

File tree

5 files changed

+340
-608
lines changed

5 files changed

+340
-608
lines changed

src/librustc/middle/borrowck/mod.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
#![allow(non_camel_case_types)]
1414

15+
use middle::cfg;
1516
use middle::dataflow::DataFlowContext;
17+
use middle::dataflow::BitwiseOperator;
1618
use middle::dataflow::DataFlowOperator;
1719
use middle::def;
1820
use euv = middle::expr_use_visitor;
@@ -126,20 +128,28 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
126128
let id_range = ast_util::compute_id_range_for_fn_body(fk, decl, body, sp, id);
127129
let (all_loans, move_data) =
128130
gather_loans::gather_loans_in_fn(this, decl, body);
131+
let cfg = cfg::CFG::new(this.tcx, body);
132+
129133
let mut loan_dfcx =
130134
DataFlowContext::new(this.tcx,
135+
"borrowck",
136+
Some(decl),
137+
&cfg,
131138
LoanDataFlowOperator,
132139
id_range,
133140
all_loans.len());
134141
for (loan_idx, loan) in all_loans.iter().enumerate() {
135142
loan_dfcx.add_gen(loan.gen_scope, loan_idx);
136143
loan_dfcx.add_kill(loan.kill_scope, loan_idx);
137144
}
138-
loan_dfcx.propagate(body);
145+
loan_dfcx.add_kills_from_flow_exits(&cfg);
146+
loan_dfcx.propagate(&cfg, body);
139147

140148
let flowed_moves = move_data::FlowedMoveData::new(move_data,
141149
this.tcx,
150+
&cfg,
142151
id_range,
152+
decl,
143153
body);
144154

145155
check_loans::check_loans(this, &loan_dfcx, flowed_moves,
@@ -753,15 +763,17 @@ fn is_statement_scope(tcx: &ty::ctxt, region: ty::Region) -> bool {
753763
}
754764
}
755765

756-
impl DataFlowOperator for LoanDataFlowOperator {
766+
impl BitwiseOperator for LoanDataFlowOperator {
757767
#[inline]
758-
fn initial_value(&self) -> bool {
759-
false // no loans in scope by default
768+
fn join(&self, succ: uint, pred: uint) -> uint {
769+
succ | pred // loans from both preds are in scope
760770
}
771+
}
761772

773+
impl DataFlowOperator for LoanDataFlowOperator {
762774
#[inline]
763-
fn join(&self, succ: uint, pred: uint) -> uint {
764-
succ | pred // loans from both preds are in scope
775+
fn initial_value(&self) -> bool {
776+
false // no loans in scope by default
765777
}
766778
}
767779

src/librustc/middle/borrowck/move_data.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ use std::rc::Rc;
2020
use std::uint;
2121
use std::collections::{HashMap, HashSet};
2222
use middle::borrowck::*;
23+
use middle::cfg;
2324
use middle::dataflow::DataFlowContext;
25+
use middle::dataflow::BitwiseOperator;
2426
use middle::dataflow::DataFlowOperator;
2527
use euv = middle::expr_use_visitor;
2628
use middle::ty;
@@ -499,22 +501,33 @@ impl MoveData {
499501
impl<'a> FlowedMoveData<'a> {
500502
pub fn new(move_data: MoveData,
501503
tcx: &'a ty::ctxt,
504+
cfg: &'a cfg::CFG,
502505
id_range: ast_util::IdRange,
506+
decl: &ast::FnDecl,
503507
body: &ast::Block)
504508
-> FlowedMoveData<'a> {
505509
let mut dfcx_moves =
506510
DataFlowContext::new(tcx,
511+
"flowed_move_data_moves",
512+
Some(decl),
513+
cfg,
507514
MoveDataFlowOperator,
508515
id_range,
509516
move_data.moves.borrow().len());
510517
let mut dfcx_assign =
511518
DataFlowContext::new(tcx,
519+
"flowed_move_data_assigns",
520+
Some(decl),
521+
cfg,
512522
AssignDataFlowOperator,
513523
id_range,
514524
move_data.var_assignments.borrow().len());
515525
move_data.add_gen_kills(tcx, &mut dfcx_moves, &mut dfcx_assign);
516-
dfcx_moves.propagate(body);
517-
dfcx_assign.propagate(body);
526+
dfcx_moves.add_kills_from_flow_exits(cfg);
527+
dfcx_assign.add_kills_from_flow_exits(cfg);
528+
dfcx_moves.propagate(cfg, body);
529+
dfcx_assign.propagate(cfg, body);
530+
518531
FlowedMoveData {
519532
move_data: move_data,
520533
dfcx_moves: dfcx_moves,
@@ -659,12 +672,21 @@ impl<'a> FlowedMoveData<'a> {
659672
}
660673
}
661674

675+
impl BitwiseOperator for MoveDataFlowOperator {
676+
#[inline]
677+
fn join(&self, succ: uint, pred: uint) -> uint {
678+
succ | pred // moves from both preds are in scope
679+
}
680+
}
681+
662682
impl DataFlowOperator for MoveDataFlowOperator {
663683
#[inline]
664684
fn initial_value(&self) -> bool {
665685
false // no loans in scope by default
666686
}
687+
}
667688

689+
impl BitwiseOperator for AssignDataFlowOperator {
668690
#[inline]
669691
fn join(&self, succ: uint, pred: uint) -> uint {
670692
succ | pred // moves from both preds are in scope
@@ -676,9 +698,4 @@ impl DataFlowOperator for AssignDataFlowOperator {
676698
fn initial_value(&self) -> bool {
677699
false // no assignments in scope by default
678700
}
679-
680-
#[inline]
681-
fn join(&self, succ: uint, pred: uint) -> uint {
682-
succ | pred // moves from both preds are in scope
683-
}
684701
}

0 commit comments

Comments
 (0)