|
15 | 15 | use self::Fragment::*;
|
16 | 16 |
|
17 | 17 | use borrowck::InteriorKind::{InteriorField, InteriorElement};
|
18 |
| -use borrowck::LoanPath; |
| 18 | +use borrowck::{self, LoanPath}; |
19 | 19 | use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend};
|
20 | 20 | use borrowck::LoanPathElem::{LpDeref, LpInterior};
|
21 | 21 | use borrowck::move_data::InvalidMovePathIndex;
|
@@ -59,6 +59,84 @@ impl Fragment {
|
59 | 59 | }
|
60 | 60 | }
|
61 | 61 |
|
| 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 | + |
62 | 140 | pub struct FragmentSets {
|
63 | 141 | /// During move_data construction, `moved_leaf_paths` tracks paths
|
64 | 142 | /// that have been used directly by being moved out of. When
|
@@ -103,6 +181,14 @@ impl FragmentSets {
|
103 | 181 | }
|
104 | 182 | }
|
105 | 183 |
|
| 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 | + |
106 | 192 | pub fn add_move(&mut self, path_index: MovePathIndex) {
|
107 | 193 | self.moved_leaf_paths.push(path_index);
|
108 | 194 | }
|
|
0 commit comments