rustc and rustc::borrowck: pass fragment info down into trans.
This commit is contained in:
parent
a0f3f2ac53
commit
d3d552b71b
@ -957,6 +957,44 @@ pub struct ctxt<'tcx> {
|
||||
/// Maps a cast expression to its kind. This is keyed on the
|
||||
/// *from* expression of the cast, not the cast itself.
|
||||
pub cast_kinds: RefCell<NodeMap<cast::CastKind>>,
|
||||
|
||||
/// Maps Fn items to a collection of fragment infos.
|
||||
///
|
||||
/// The main goal is to identify data (each of which may be moved
|
||||
/// or assigned) whose subparts are not moved nor assigned
|
||||
/// (i.e. their state is *unfragmented*) and corresponding ast
|
||||
/// nodes where the path to that data is moved or assigned.
|
||||
///
|
||||
/// In the long term, unfragmented values will have their
|
||||
/// destructor entirely driven by a single stack-local drop-flag,
|
||||
/// and their parents, the collections of the unfragmented values
|
||||
/// (or more simply, "fragmented values"), are mapped to the
|
||||
/// corresponding collections of stack-local drop-flags.
|
||||
///
|
||||
/// (However, in the short term that is not the case; e.g. some
|
||||
/// unfragmented paths still need to be zeroed, namely when they
|
||||
/// reference parent data from an outer scope that was not
|
||||
/// entirely moved, and therefore that needs to be zeroed so that
|
||||
/// we do not get double-drop when we hit the end of the parent
|
||||
/// scope.)
|
||||
///
|
||||
/// Also: currently the table solely holds keys for node-ids of
|
||||
/// unfragmented values (see `FragmentInfo` enum definition), but
|
||||
/// longer-term we will need to also store mappings from
|
||||
/// fragmented data to the set of unfragmented pieces that
|
||||
/// constitute it.
|
||||
pub fragment_infos: RefCell<DefIdMap<Vec<FragmentInfo>>>,
|
||||
}
|
||||
|
||||
/// Describes the fragment-state associated with a NodeId.
|
||||
///
|
||||
/// Currently only unfragmented paths have entries in the table,
|
||||
/// but longer-term this enum is expected to expand to also
|
||||
/// include data for fragmented paths.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum FragmentInfo {
|
||||
Moved { var: NodeId, move_expr: NodeId },
|
||||
Assigned { var: NodeId, assign_expr: NodeId, assignee_id: NodeId },
|
||||
}
|
||||
|
||||
impl<'tcx> ctxt<'tcx> {
|
||||
@ -3498,6 +3536,7 @@ impl<'tcx> ctxt<'tcx> {
|
||||
const_qualif_map: RefCell::new(NodeMap()),
|
||||
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
|
||||
cast_kinds: RefCell::new(NodeMap()),
|
||||
fragment_infos: RefCell::new(DefIdMap()),
|
||||
}, f)
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ fn owned_ptr_base_path_rc<'tcx>(loan_path: &Rc<LoanPath<'tcx>>) -> Rc<LoanPath<'
|
||||
struct CheckLoanCtxt<'a, 'tcx: 'a> {
|
||||
bccx: &'a BorrowckCtxt<'a, 'tcx>,
|
||||
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
|
||||
move_data: move_data::FlowedMoveData<'a, 'tcx>,
|
||||
move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
|
||||
all_loans: &'a [Loan<'tcx>],
|
||||
param_env: &'a ty::ParameterEnvironment<'a, 'tcx>,
|
||||
}
|
||||
@ -191,7 +191,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
|
||||
|
||||
pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
dfcx_loans: &LoanDataFlow<'b, 'tcx>,
|
||||
move_data: move_data::FlowedMoveData<'c, 'tcx>,
|
||||
move_data: &move_data::FlowedMoveData<'c, 'tcx>,
|
||||
all_loans: &[Loan<'tcx>],
|
||||
fn_id: ast::NodeId,
|
||||
decl: &ast::FnDecl,
|
||||
|
@ -15,7 +15,7 @@
|
||||
use self::Fragment::*;
|
||||
|
||||
use borrowck::InteriorKind::{InteriorField, InteriorElement};
|
||||
use borrowck::LoanPath;
|
||||
use borrowck::{self, LoanPath};
|
||||
use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend};
|
||||
use borrowck::LoanPathElem::{LpDeref, LpInterior};
|
||||
use borrowck::move_data::InvalidMovePathIndex;
|
||||
@ -59,6 +59,84 @@ impl Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_unfragmented_map(this: &mut borrowck::BorrowckCtxt,
|
||||
move_data: &MoveData,
|
||||
id: ast::NodeId) {
|
||||
let fr = &move_data.fragments.borrow();
|
||||
|
||||
// For now, don't care about other kinds of fragments; the precise
|
||||
// classfication of all paths for non-zeroing *drop* needs them,
|
||||
// but the loose approximation used by non-zeroing moves does not.
|
||||
let moved_leaf_paths = fr.moved_leaf_paths();
|
||||
let assigned_leaf_paths = fr.assigned_leaf_paths();
|
||||
|
||||
let mut fragment_infos = Vec::with_capacity(moved_leaf_paths.len());
|
||||
|
||||
let find_var_id = |move_path_index: MovePathIndex| -> Option<ast::NodeId> {
|
||||
let lp = move_data.path_loan_path(move_path_index);
|
||||
match lp.kind {
|
||||
LpVar(var_id) => Some(var_id),
|
||||
LpUpvar(ty::UpvarId { var_id, closure_expr_id }) => {
|
||||
// The `var_id` is unique *relative to* the current function.
|
||||
// (Check that we are indeed talking about the same function.)
|
||||
assert_eq!(id, closure_expr_id);
|
||||
Some(var_id)
|
||||
}
|
||||
LpDowncast(..) | LpExtend(..) => {
|
||||
// This simple implementation of non-zeroing move does
|
||||
// not attempt to deal with tracking substructure
|
||||
// accurately in the general case.
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let moves = move_data.moves.borrow();
|
||||
for &move_path_index in moved_leaf_paths {
|
||||
let var_id = match find_var_id(move_path_index) {
|
||||
None => continue,
|
||||
Some(var_id) => var_id,
|
||||
};
|
||||
|
||||
move_data.each_applicable_move(move_path_index, |move_index| {
|
||||
let info = ty::FragmentInfo::Moved {
|
||||
var: var_id,
|
||||
move_expr: moves[move_index.get()].id,
|
||||
};
|
||||
debug!("fragment_infos push({:?} \
|
||||
due to move_path_index: {} move_index: {}",
|
||||
info, move_path_index.get(), move_index.get());
|
||||
fragment_infos.push(info);
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
for &move_path_index in assigned_leaf_paths {
|
||||
let var_id = match find_var_id(move_path_index) {
|
||||
None => continue,
|
||||
Some(var_id) => var_id,
|
||||
};
|
||||
|
||||
let var_assigns = move_data.var_assignments.borrow();
|
||||
for var_assign in var_assigns.iter()
|
||||
.filter(|&assign| assign.path == move_path_index)
|
||||
{
|
||||
let info = ty::FragmentInfo::Assigned {
|
||||
var: var_id,
|
||||
assign_expr: var_assign.id,
|
||||
assignee_id: var_assign.assignee_id,
|
||||
};
|
||||
debug!("fragment_infos push({:?} due to var_assignment", info);
|
||||
fragment_infos.push(info);
|
||||
}
|
||||
}
|
||||
|
||||
let mut fraginfo_map = this.tcx.fragment_infos.borrow_mut();
|
||||
let fn_did = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
|
||||
let prev = fraginfo_map.insert(fn_did, fragment_infos);
|
||||
assert!(prev.is_none());
|
||||
}
|
||||
|
||||
pub struct FragmentSets {
|
||||
/// During move_data construction, `moved_leaf_paths` tracks paths
|
||||
/// that have been used directly by being moved out of. When
|
||||
@ -103,6 +181,14 @@ impl FragmentSets {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn moved_leaf_paths(&self) -> &[MovePathIndex] {
|
||||
&self.moved_leaf_paths
|
||||
}
|
||||
|
||||
pub fn assigned_leaf_paths(&self) -> &[MovePathIndex] {
|
||||
&self.assigned_leaf_paths
|
||||
}
|
||||
|
||||
pub fn add_move(&mut self, path_index: MovePathIndex) {
|
||||
self.moved_leaf_paths.push(path_index);
|
||||
}
|
||||
|
@ -169,12 +169,16 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
|
||||
|
||||
check_loans::check_loans(this,
|
||||
&loan_dfcx,
|
||||
flowed_moves,
|
||||
&flowed_moves,
|
||||
&all_loans[..],
|
||||
id,
|
||||
decl,
|
||||
body);
|
||||
|
||||
move_data::fragments::build_unfragmented_map(this,
|
||||
&flowed_moves.move_data,
|
||||
id);
|
||||
|
||||
visit::walk_fn(this, fk, decl, body, sp);
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,9 @@ pub struct Assignment {
|
||||
|
||||
/// span of node where assignment occurs
|
||||
pub span: Span,
|
||||
|
||||
/// id for l-value expression on lhs of assignment
|
||||
pub assignee_id: ast::NodeId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -412,6 +415,7 @@ impl<'tcx> MoveData<'tcx> {
|
||||
path: path_index,
|
||||
id: assign_id,
|
||||
span: span,
|
||||
assignee_id: assignee_id,
|
||||
};
|
||||
|
||||
if self.is_var_path(path_index) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user