Skip to content

Commit

Permalink
Revise dataflow to do a cfg-driven walk.
Browse files Browse the repository at this point in the history
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.)
  • Loading branch information
pnkfelix committed Jun 18, 2014
1 parent fef63e2 commit 75340f4
Show file tree
Hide file tree
Showing 5 changed files with 340 additions and 608 deletions.
24 changes: 18 additions & 6 deletions src/librustc/middle/borrowck/mod.rs
Expand Up @@ -12,7 +12,9 @@

#![allow(non_camel_case_types)]

use middle::cfg;
use middle::dataflow::DataFlowContext;
use middle::dataflow::BitwiseOperator;
use middle::dataflow::DataFlowOperator;
use middle::def;
use euv = middle::expr_use_visitor;
Expand Down Expand Up @@ -126,20 +128,28 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
let id_range = ast_util::compute_id_range_for_fn_body(fk, decl, body, sp, id);
let (all_loans, move_data) =
gather_loans::gather_loans_in_fn(this, decl, body);
let cfg = cfg::CFG::new(this.tcx, body);

let mut loan_dfcx =
DataFlowContext::new(this.tcx,
"borrowck",
Some(decl),
&cfg,
LoanDataFlowOperator,
id_range,
all_loans.len());
for (loan_idx, loan) in all_loans.iter().enumerate() {
loan_dfcx.add_gen(loan.gen_scope, loan_idx);
loan_dfcx.add_kill(loan.kill_scope, loan_idx);
}
loan_dfcx.propagate(body);
loan_dfcx.add_kills_from_flow_exits(&cfg);
loan_dfcx.propagate(&cfg, body);

let flowed_moves = move_data::FlowedMoveData::new(move_data,
this.tcx,
&cfg,
id_range,
decl,
body);

check_loans::check_loans(this, &loan_dfcx, flowed_moves,
Expand Down Expand Up @@ -753,15 +763,17 @@ fn is_statement_scope(tcx: &ty::ctxt, region: ty::Region) -> bool {
}
}

impl DataFlowOperator for LoanDataFlowOperator {
impl BitwiseOperator for LoanDataFlowOperator {
#[inline]
fn initial_value(&self) -> bool {
false // no loans in scope by default
fn join(&self, succ: uint, pred: uint) -> uint {
succ | pred // loans from both preds are in scope
}
}

impl DataFlowOperator for LoanDataFlowOperator {
#[inline]
fn join(&self, succ: uint, pred: uint) -> uint {
succ | pred // loans from both preds are in scope
fn initial_value(&self) -> bool {
false // no loans in scope by default
}
}

Expand Down
31 changes: 24 additions & 7 deletions src/librustc/middle/borrowck/move_data.rs
Expand Up @@ -20,7 +20,9 @@ use std::rc::Rc;
use std::uint;
use std::collections::{HashMap, HashSet};
use middle::borrowck::*;
use middle::cfg;
use middle::dataflow::DataFlowContext;
use middle::dataflow::BitwiseOperator;
use middle::dataflow::DataFlowOperator;
use euv = middle::expr_use_visitor;
use middle::ty;
Expand Down Expand Up @@ -499,22 +501,33 @@ impl MoveData {
impl<'a> FlowedMoveData<'a> {
pub fn new(move_data: MoveData,
tcx: &'a ty::ctxt,
cfg: &'a cfg::CFG,
id_range: ast_util::IdRange,
decl: &ast::FnDecl,
body: &ast::Block)
-> FlowedMoveData<'a> {
let mut dfcx_moves =
DataFlowContext::new(tcx,
"flowed_move_data_moves",
Some(decl),
cfg,
MoveDataFlowOperator,
id_range,
move_data.moves.borrow().len());
let mut dfcx_assign =
DataFlowContext::new(tcx,
"flowed_move_data_assigns",
Some(decl),
cfg,
AssignDataFlowOperator,
id_range,
move_data.var_assignments.borrow().len());
move_data.add_gen_kills(tcx, &mut dfcx_moves, &mut dfcx_assign);
dfcx_moves.propagate(body);
dfcx_assign.propagate(body);
dfcx_moves.add_kills_from_flow_exits(cfg);
dfcx_assign.add_kills_from_flow_exits(cfg);
dfcx_moves.propagate(cfg, body);
dfcx_assign.propagate(cfg, body);

FlowedMoveData {
move_data: move_data,
dfcx_moves: dfcx_moves,
Expand Down Expand Up @@ -659,12 +672,21 @@ impl<'a> FlowedMoveData<'a> {
}
}

impl BitwiseOperator for MoveDataFlowOperator {
#[inline]
fn join(&self, succ: uint, pred: uint) -> uint {
succ | pred // moves from both preds are in scope
}
}

impl DataFlowOperator for MoveDataFlowOperator {
#[inline]
fn initial_value(&self) -> bool {
false // no loans in scope by default
}
}

impl BitwiseOperator for AssignDataFlowOperator {
#[inline]
fn join(&self, succ: uint, pred: uint) -> uint {
succ | pred // moves from both preds are in scope
Expand All @@ -676,9 +698,4 @@ impl DataFlowOperator for AssignDataFlowOperator {
fn initial_value(&self) -> bool {
false // no assignments in scope by default
}

#[inline]
fn join(&self, succ: uint, pred: uint) -> uint {
succ | pred // moves from both preds are in scope
}
}

0 comments on commit 75340f4

Please sign in to comment.