Skip to content

Commit d3d552b

Browse files
committed
rustc and rustc::borrowck: pass fragment info down into trans.
1 parent a0f3f2a commit d3d552b

File tree

5 files changed

+137
-4
lines changed

5 files changed

+137
-4
lines changed

src/librustc/middle/ty.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,44 @@ pub struct ctxt<'tcx> {
957957
/// Maps a cast expression to its kind. This is keyed on the
958958
/// *from* expression of the cast, not the cast itself.
959959
pub cast_kinds: RefCell<NodeMap<cast::CastKind>>,
960+
961+
/// Maps Fn items to a collection of fragment infos.
962+
///
963+
/// The main goal is to identify data (each of which may be moved
964+
/// or assigned) whose subparts are not moved nor assigned
965+
/// (i.e. their state is *unfragmented*) and corresponding ast
966+
/// nodes where the path to that data is moved or assigned.
967+
///
968+
/// In the long term, unfragmented values will have their
969+
/// destructor entirely driven by a single stack-local drop-flag,
970+
/// and their parents, the collections of the unfragmented values
971+
/// (or more simply, "fragmented values"), are mapped to the
972+
/// corresponding collections of stack-local drop-flags.
973+
///
974+
/// (However, in the short term that is not the case; e.g. some
975+
/// unfragmented paths still need to be zeroed, namely when they
976+
/// reference parent data from an outer scope that was not
977+
/// entirely moved, and therefore that needs to be zeroed so that
978+
/// we do not get double-drop when we hit the end of the parent
979+
/// scope.)
980+
///
981+
/// Also: currently the table solely holds keys for node-ids of
982+
/// unfragmented values (see `FragmentInfo` enum definition), but
983+
/// longer-term we will need to also store mappings from
984+
/// fragmented data to the set of unfragmented pieces that
985+
/// constitute it.
986+
pub fragment_infos: RefCell<DefIdMap<Vec<FragmentInfo>>>,
987+
}
988+
989+
/// Describes the fragment-state associated with a NodeId.
990+
///
991+
/// Currently only unfragmented paths have entries in the table,
992+
/// but longer-term this enum is expected to expand to also
993+
/// include data for fragmented paths.
994+
#[derive(Copy, Clone, Debug)]
995+
pub enum FragmentInfo {
996+
Moved { var: NodeId, move_expr: NodeId },
997+
Assigned { var: NodeId, assign_expr: NodeId, assignee_id: NodeId },
960998
}
961999

9621000
impl<'tcx> ctxt<'tcx> {
@@ -3498,6 +3536,7 @@ impl<'tcx> ctxt<'tcx> {
34983536
const_qualif_map: RefCell::new(NodeMap()),
34993537
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
35003538
cast_kinds: RefCell::new(NodeMap()),
3539+
fragment_infos: RefCell::new(DefIdMap()),
35013540
}, f)
35023541
}
35033542

src/librustc_borrowck/borrowck/check_loans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ fn owned_ptr_base_path_rc<'tcx>(loan_path: &Rc<LoanPath<'tcx>>) -> Rc<LoanPath<'
8686
struct CheckLoanCtxt<'a, 'tcx: 'a> {
8787
bccx: &'a BorrowckCtxt<'a, 'tcx>,
8888
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
89-
move_data: move_data::FlowedMoveData<'a, 'tcx>,
89+
move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
9090
all_loans: &'a [Loan<'tcx>],
9191
param_env: &'a ty::ParameterEnvironment<'a, 'tcx>,
9292
}
@@ -191,7 +191,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
191191

192192
pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
193193
dfcx_loans: &LoanDataFlow<'b, 'tcx>,
194-
move_data: move_data::FlowedMoveData<'c, 'tcx>,
194+
move_data: &move_data::FlowedMoveData<'c, 'tcx>,
195195
all_loans: &[Loan<'tcx>],
196196
fn_id: ast::NodeId,
197197
decl: &ast::FnDecl,

src/librustc_borrowck/borrowck/fragments.rs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use self::Fragment::*;
1616

1717
use borrowck::InteriorKind::{InteriorField, InteriorElement};
18-
use borrowck::LoanPath;
18+
use borrowck::{self, LoanPath};
1919
use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend};
2020
use borrowck::LoanPathElem::{LpDeref, LpInterior};
2121
use borrowck::move_data::InvalidMovePathIndex;
@@ -59,6 +59,84 @@ impl Fragment {
5959
}
6060
}
6161

62+
pub fn build_unfragmented_map(this: &mut borrowck::BorrowckCtxt,
63+
move_data: &MoveData,
64+
id: ast::NodeId) {
65+
let fr = &move_data.fragments.borrow();
66+
67+
// For now, don't care about other kinds of fragments; the precise
68+
// classfication of all paths for non-zeroing *drop* needs them,
69+
// but the loose approximation used by non-zeroing moves does not.
70+
let moved_leaf_paths = fr.moved_leaf_paths();
71+
let assigned_leaf_paths = fr.assigned_leaf_paths();
72+
73+
let mut fragment_infos = Vec::with_capacity(moved_leaf_paths.len());
74+
75+
let find_var_id = |move_path_index: MovePathIndex| -> Option<ast::NodeId> {
76+
let lp = move_data.path_loan_path(move_path_index);
77+
match lp.kind {
78+
LpVar(var_id) => Some(var_id),
79+
LpUpvar(ty::UpvarId { var_id, closure_expr_id }) => {
80+
// The `var_id` is unique *relative to* the current function.
81+
// (Check that we are indeed talking about the same function.)
82+
assert_eq!(id, closure_expr_id);
83+
Some(var_id)
84+
}
85+
LpDowncast(..) | LpExtend(..) => {
86+
// This simple implementation of non-zeroing move does
87+
// not attempt to deal with tracking substructure
88+
// accurately in the general case.
89+
None
90+
}
91+
}
92+
};
93+
94+
let moves = move_data.moves.borrow();
95+
for &move_path_index in moved_leaf_paths {
96+
let var_id = match find_var_id(move_path_index) {
97+
None => continue,
98+
Some(var_id) => var_id,
99+
};
100+
101+
move_data.each_applicable_move(move_path_index, |move_index| {
102+
let info = ty::FragmentInfo::Moved {
103+
var: var_id,
104+
move_expr: moves[move_index.get()].id,
105+
};
106+
debug!("fragment_infos push({:?} \
107+
due to move_path_index: {} move_index: {}",
108+
info, move_path_index.get(), move_index.get());
109+
fragment_infos.push(info);
110+
true
111+
});
112+
}
113+
114+
for &move_path_index in assigned_leaf_paths {
115+
let var_id = match find_var_id(move_path_index) {
116+
None => continue,
117+
Some(var_id) => var_id,
118+
};
119+
120+
let var_assigns = move_data.var_assignments.borrow();
121+
for var_assign in var_assigns.iter()
122+
.filter(|&assign| assign.path == move_path_index)
123+
{
124+
let info = ty::FragmentInfo::Assigned {
125+
var: var_id,
126+
assign_expr: var_assign.id,
127+
assignee_id: var_assign.assignee_id,
128+
};
129+
debug!("fragment_infos push({:?} due to var_assignment", info);
130+
fragment_infos.push(info);
131+
}
132+
}
133+
134+
let mut fraginfo_map = this.tcx.fragment_infos.borrow_mut();
135+
let fn_did = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
136+
let prev = fraginfo_map.insert(fn_did, fragment_infos);
137+
assert!(prev.is_none());
138+
}
139+
62140
pub struct FragmentSets {
63141
/// During move_data construction, `moved_leaf_paths` tracks paths
64142
/// that have been used directly by being moved out of. When
@@ -103,6 +181,14 @@ impl FragmentSets {
103181
}
104182
}
105183

184+
pub fn moved_leaf_paths(&self) -> &[MovePathIndex] {
185+
&self.moved_leaf_paths
186+
}
187+
188+
pub fn assigned_leaf_paths(&self) -> &[MovePathIndex] {
189+
&self.assigned_leaf_paths
190+
}
191+
106192
pub fn add_move(&mut self, path_index: MovePathIndex) {
107193
self.moved_leaf_paths.push(path_index);
108194
}

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,16 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
169169

170170
check_loans::check_loans(this,
171171
&loan_dfcx,
172-
flowed_moves,
172+
&flowed_moves,
173173
&all_loans[..],
174174
id,
175175
decl,
176176
body);
177177

178+
move_data::fragments::build_unfragmented_map(this,
179+
&flowed_moves.move_data,
180+
id);
181+
178182
visit::walk_fn(this, fk, decl, body, sp);
179183
}
180184

src/librustc_borrowck/borrowck/move_data.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ pub struct Assignment {
159159

160160
/// span of node where assignment occurs
161161
pub span: Span,
162+
163+
/// id for l-value expression on lhs of assignment
164+
pub assignee_id: ast::NodeId,
162165
}
163166

164167
#[derive(Copy, Clone)]
@@ -412,6 +415,7 @@ impl<'tcx> MoveData<'tcx> {
412415
path: path_index,
413416
id: assign_id,
414417
span: span,
418+
assignee_id: assignee_id,
415419
};
416420

417421
if self.is_var_path(path_index) {

0 commit comments

Comments
 (0)