diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index a25c3afd63c2..1fae97566d0a 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -35,7 +35,7 @@ crate struct BorrowSet<'tcx> { /// NOTE: A given location may activate more than one borrow in the future /// when more general two-phase borrow support is introduced, but for now we /// only need to store one borrow index - crate activation_map: FxHashMap>, + crate activation_map: FxHashMap>, /// Every borrow has a region; this maps each such regions back to /// its borrow-indexes. @@ -131,7 +131,7 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { mir: &'a Mir<'tcx>, idx_vec: IndexVec>, location_map: FxHashMap, - activation_map: FxHashMap>, + activation_map: FxHashMap>, region_map: FxHashMap, FxHashSet>, local_map: FxHashMap>, region_span_map: FxHashMap, @@ -230,8 +230,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { borrow_data.activation_location = Some(location); self.activation_map .entry(location) - .or_insert(FxHashSet()) - .insert(borrow_index); + .or_insert(Vec::new()) + .push(borrow_index); } None => {} diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 2e64626e2ea4..dd76b883d63d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1267,36 +1267,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with // another borrow. - let domain = flow_state.borrows.operator(); - let data = domain.borrows(); - flow_state.borrows.each_gen_bit(|gen| { - if gen.is_activation() { - let borrow_index = gen.borrow_index(); - let borrow = &data[borrow_index]; - // currently the flow analysis registers - // activations for both mutable and immutable - // borrows. So make sure we are talking about a - // mutable borrow before we check it. - match borrow.kind { - BorrowKind::Shared => return, - BorrowKind::Unique | BorrowKind::Mut { .. } => {} - } + let borrows = flow_state.borrows.operator(); + for &borrow_index in borrows.activations_at_location(location) { + let borrow = &borrows.borrows()[borrow_index]; - self.access_place( - ContextKind::Activation.new(location), - (&borrow.borrowed_place, span), - ( - Deep, - Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index), - ), - LocalMutationIsAllowed::No, - flow_state, - ); - // We do not need to call `check_if_path_or_subpath_is_moved` - // again, as we already called it when we made the - // initial reservation. - } - }); + // only mutable borrows should be 2-phase + assert!(match borrow.kind { + BorrowKind::Shared => false, + BorrowKind::Unique | BorrowKind::Mut { .. } => true, + }); + + self.access_place( + ContextKind::Activation.new(location), + (&borrow.borrowed_place, span), + ( + Deep, + Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index), + ), + LocalMutationIsAllowed::No, + flow_state, + ); + // We do not need to call `check_if_path_or_subpath_is_moved` + // again, as we already called it when we made the + // initial reservation. + } } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 25f1278d7fa6..190d08e83de4 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -156,6 +156,13 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } } + crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] { + self.borrow_set.activation_map + .get(&location) + .map(|activations| &activations[..]) + .unwrap_or(&[]) + } + /// Performs the activations for a given location fn perform_activations_at_location(&self, sets: &mut BlockSets,