diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index e0b03aec69a3..4dbb613f8fb6 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -34,9 +34,9 @@ use dataflow::MoveDataParamEnv; use dataflow::{DataflowAnalysis, DataflowResultsConsumer}; use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use dataflow::{EverInitializedLvals, MovingOutStatements}; -use dataflow::{Borrows, BorrowData, ReserveOrActivateIndex}; +use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex}; use dataflow::{ActiveBorrows, Reservations}; -use dataflow::indexes::{BorrowIndex}; +use dataflow::indexes::BorrowIndex; use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -149,9 +149,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( param_env: param_env, }; let body_id = match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::StructCtor | - DefPathData::EnumVariant(_) => None, - _ => Some(tcx.hir.body_owned_by(id)) + DefPathData::StructCtor | DefPathData::EnumVariant(_) => None, + _ => Some(tcx.hir.body_owned_by(id)), }; let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); @@ -217,8 +216,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( move_data: &mdpe.move_data, param_env: param_env, locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) { - hir::BodyOwnerKind::Const | - hir::BodyOwnerKind::Static(_) => false, + hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, hir::BodyOwnerKind::Fn => true, }, storage_dead_or_drop_error_reported_l: FxHashSet(), @@ -241,18 +239,20 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // In practice it is easier to be looser; in particular, // it is okay for the kill-sets to hold activation bits. DebugFormatted::new(&(i.kind(), rs.location(i))) - }); + }, + ); let flow_active_borrows = { let reservations_on_entry = flow_reservations.0.sets.entry_set_state(); let reservations = flow_reservations.0.operator; - let a = DataflowAnalysis::new_with_entry_sets(mir, - &dead_unwinds, - Cow::Borrowed(reservations_on_entry), - ActiveBorrows::new(reservations)); - let results = a.run(tcx, - id, - &attributes, - |ab, i| DebugFormatted::new(&(i.kind(), ab.location(i)))); + let a = DataflowAnalysis::new_with_entry_sets( + mir, + &dead_unwinds, + Cow::Borrowed(reservations_on_entry), + ActiveBorrows::new(reservations), + ); + let results = a.run(tcx, id, &attributes, |ab, i| { + DebugFormatted::new(&(i.kind(), ab.location(i))) + }); FlowAtLocation::new(results) }; @@ -551,9 +551,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx } }); } - TerminatorKind::Goto { target: _ } | - TerminatorKind::Unreachable | - TerminatorKind::FalseEdges { .. } => { + TerminatorKind::Goto { target: _ } + | TerminatorKind::Unreachable + | TerminatorKind::FalseEdges { .. } => { // no data used, thus irrelevant to borrowck } } @@ -648,13 +648,12 @@ enum LocalMutationIsAllowed { /// We want use of immutable upvars to cause a "write to immutable upvar" /// error, not an "reassignment" error. ExceptUpvars, - No + No, } struct AccessErrorsReported { mutability_error: bool, - #[allow(dead_code)] - conflict_error: bool + #[allow(dead_code)] conflict_error: bool, } #[derive(Copy, Clone)] @@ -704,9 +703,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Activation(_, borrow_index) = rw { if self.reservation_error_reported.contains(&place_span.0) { - debug!("skipping access_place for activation of invalid reservation \ - place: {:?} borrow_index: {:?}", place_span.0, borrow_index); - return AccessErrorsReported { mutability_error: false, conflict_error: true }; + debug!( + "skipping access_place for activation of invalid reservation \ + place: {:?} borrow_index: {:?}", + place_span.0, + borrow_index + ); + return AccessErrorsReported { + mutability_error: false, + conflict_error: true, + }; } } @@ -715,7 +721,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let conflict_error = self.check_access_for_conflict(context, place_span, sd, rw, flow_state); - AccessErrorsReported { mutability_error, conflict_error } + AccessErrorsReported { + mutability_error, + conflict_error, + } } fn check_access_for_conflict( @@ -738,22 +747,26 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // NOTE: *reservations* do conflict with themselves; // thus aren't injecting unsoundenss w/ this check.) - (Activation(_, activating), _) if activating == index.borrow_index() => - { - debug!("check_access_for_conflict place_span: {:?} sd: {:?} rw: {:?} \ - skipping {:?} b/c activation of same borrow_index: {:?}", - place_span, sd, rw, (index, borrow), index.borrow_index()); + (Activation(_, activating), _) if activating == index.borrow_index() => { + debug!( + "check_access_for_conflict place_span: {:?} sd: {:?} rw: {:?} \ + skipping {:?} b/c activation of same borrow_index: {:?}", + place_span, + sd, + rw, + (index, borrow), + index.borrow_index() + ); Control::Continue } - (Read(_), BorrowKind::Shared) | - (Reservation(..), BorrowKind::Shared) => Control::Continue, + (Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared) => { + Control::Continue + } - (Read(kind), BorrowKind::Unique) | - (Read(kind), BorrowKind::Mut) => { + (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => { // Reading from mere reservations of mutable-borrows is OK. - if this.tcx.sess.opts.debugging_opts.two_phase_borrows && - index.is_reservation() + if this.tcx.sess.opts.debugging_opts.two_phase_borrows && index.is_reservation() { return Control::Continue; } @@ -781,20 +794,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Control::Break } - (Reservation(kind), BorrowKind::Unique) | - (Reservation(kind), BorrowKind::Mut) | - (Activation(kind, _), _) | - (Write(kind), _) => { - + (Reservation(kind), BorrowKind::Unique) + | (Reservation(kind), BorrowKind::Mut) + | (Activation(kind, _), _) + | (Write(kind), _) => { match rw { Reservation(_) => { - debug!("recording invalid reservation of \ - place: {:?}", place_span.0); + debug!( + "recording invalid reservation of \ + place: {:?}", + place_span.0 + ); this.reservation_error_reported.insert(place_span.0.clone()); } Activation(_, activating) => { - debug!("observing check_place for activation of \ - borrow_index: {:?}", activating); + debug!( + "observing check_place for activation of \ + borrow_index: {:?}", + activating + ); } Read(..) | Write(..) => {} } @@ -818,8 +836,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { WriteKind::StorageDeadOrDrop => { error_reported = true; this.report_borrowed_value_does_not_live_long_enough( - context, borrow, place_span.1, - flow_state.borrows.operator()); + context, + borrow, + place_span.1, + flow_state.borrows.operator(), + ); } WriteKind::Mutate => { error_reported = true; @@ -917,10 +938,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - Rvalue::Use(ref operand) | - Rvalue::Repeat(ref operand, _) | - Rvalue::UnaryOp(_ /*un_op*/, ref operand) | - Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => { + Rvalue::Use(ref operand) + | Rvalue::Repeat(ref operand, _) + | Rvalue::UnaryOp(_ /*un_op*/, ref operand) + | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => { self.consume_operand(context, (operand, span), flow_state) } @@ -945,8 +966,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) | - Rvalue::CheckedBinaryOp(_bin_op, ref operand1, ref operand2) => { + Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) + | Rvalue::CheckedBinaryOp(_bin_op, ref operand1, ref operand2) => { self.consume_operand(context, (operand1, span), flow_state); self.consume_operand(context, (operand2, span), flow_state); } @@ -1015,12 +1036,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Returns whether a borrow of this place is invalidated when the function /// exits - fn check_for_invalidation_at_exit(&mut self, - context: Context, - borrow: &BorrowData<'tcx>, - span: Span, - flow_state: &Flows<'cx, 'gcx, 'tcx>) - { + fn check_for_invalidation_at_exit( + &mut self, + context: Context, + borrow: &BorrowData<'tcx>, + span: Span, + flow_state: &Flows<'cx, 'gcx, 'tcx>, + ) { debug!("check_for_invalidation_at_exit({:?})", borrow); let place = &borrow.borrowed_place; let root_place = self.prefixes(place, PrefixSet::All).last().unwrap(); @@ -1061,11 +1083,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // FIXME: replace this with a proper borrow_conflicts_with_place when // that is merged. - let sd = if might_be_alive { - Deep - } else { - Shallow(None) - }; + let sd = if might_be_alive { Deep } else { Shallow(None) }; if self.places_conflict(place, root_place, sd) { debug!("check_for_invalidation_at_exit({:?}): INVALID", place); @@ -1075,16 +1093,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, borrow, span.end_point(), - flow_state.borrows.operator() + flow_state.borrows.operator(), ) } } - fn check_activations(&mut self, - location: Location, - span: Span, - flow_state: &Flows<'cx, 'gcx, 'tcx>) - { + fn check_activations( + &mut self, + location: Location, + span: Span, + flow_state: &Flows<'cx, 'gcx, 'tcx>, + ) { if !self.tcx.sess.opts.debugging_opts.two_phase_borrows { return; } @@ -1095,8 +1114,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let domain = flow_state.borrows.operator(); let data = domain.borrows(); flow_state.borrows.each_gen_bit(|gen| { - if gen.is_activation() - { + if gen.is_activation() { let borrow_index = gen.borrow_index(); let borrow = &data[borrow_index]; // currently the flow analysis registers @@ -1105,16 +1123,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // mutable borrow before we check it. match borrow.kind { BorrowKind::Shared => return, - BorrowKind::Unique | - BorrowKind::Mut => {} + BorrowKind::Unique | BorrowKind::Mut => {} } - self.access_place(ContextKind::Activation.new(location), - (&borrow.borrowed_place, span), - (Deep, Activation(WriteKind::MutableBorrow(borrow.kind), - borrow_index)), - LocalMutationIsAllowed::No, - flow_state); + 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_is_moved` // again, as we already called it when we made the // initial reservation. @@ -1135,7 +1156,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Ok(()) = self.is_mutable(place, LocalMutationIsAllowed::No) { return; } - debug!("check_if_reassignment_to_immutable_state({:?}) - is an imm local", place); + debug!( + "check_if_reassignment_to_immutable_state({:?}) - is an imm local", + place + ); for i in flow_state.ever_inits.elems_incoming() { let init = self.move_data.inits[i]; @@ -1364,14 +1388,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); let mut error_reported = false; match kind { - Reservation(WriteKind::MutableBorrow(BorrowKind::Unique)) | - Write(WriteKind::MutableBorrow(BorrowKind::Unique)) => { + Reservation(WriteKind::MutableBorrow(BorrowKind::Unique)) + | Write(WriteKind::MutableBorrow(BorrowKind::Unique)) => { if let Err(_place_err) = self.is_mutable(place, LocalMutationIsAllowed::Yes) { span_bug!(span, "&unique borrow for {:?} should not fail", place); } } - Reservation(WriteKind::MutableBorrow(BorrowKind::Mut)) | - Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => if let Err(place_err) = + Reservation(WriteKind::MutableBorrow(BorrowKind::Mut)) + | Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) { error_reported = true; @@ -1393,8 +1417,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); }, - Reservation(WriteKind::Mutate) | - Write(WriteKind::Mutate) => { + Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) { error_reported = true; @@ -1415,12 +1438,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); } } - Reservation(WriteKind::Move) | - Reservation(WriteKind::StorageDeadOrDrop) | - Reservation(WriteKind::MutableBorrow(BorrowKind::Shared)) | - Write(WriteKind::Move) | - Write(WriteKind::StorageDeadOrDrop) | - Write(WriteKind::MutableBorrow(BorrowKind::Shared)) => { + Reservation(WriteKind::Move) + | Reservation(WriteKind::StorageDeadOrDrop) + | Reservation(WriteKind::MutableBorrow(BorrowKind::Shared)) + | Write(WriteKind::Move) + | Write(WriteKind::StorageDeadOrDrop) + | Write(WriteKind::MutableBorrow(BorrowKind::Shared)) => { if let Err(_place_err) = self.is_mutable(place, is_local_mutation_allowed) { self.tcx.sess.delay_span_bug( span, @@ -1435,10 +1458,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Activation(..) => {} // permission checks are done at Reservation point. - Read(ReadKind::Borrow(BorrowKind::Unique)) | - Read(ReadKind::Borrow(BorrowKind::Mut)) | - Read(ReadKind::Borrow(BorrowKind::Shared)) | - Read(ReadKind::Copy) => {} // Access authorized + Read(ReadKind::Borrow(BorrowKind::Unique)) + | Read(ReadKind::Borrow(BorrowKind::Mut)) + | Read(ReadKind::Borrow(BorrowKind::Shared)) + | Read(ReadKind::Copy) => {} // Access authorized } error_reported @@ -1455,8 +1478,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = &self.mir.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { - LocalMutationIsAllowed::Yes | - LocalMutationIsAllowed::ExceptUpvars => Ok(()), + LocalMutationIsAllowed::Yes | LocalMutationIsAllowed::ExceptUpvars => { + Ok(()) + } LocalMutationIsAllowed::No => Err(place), }, Mutability::Mut => Ok(()), @@ -1481,13 +1505,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Mutably borrowed data is mutable, but only if we have a // unique path to the `&mut` hir::MutMutable => { - let mode = match - self.is_upvar_field_projection(&proj.base) + let mode = match self.is_upvar_field_projection(&proj.base) { - Some(field) if { - self.mir.upvar_decls[field.index()].by_ref - } => is_local_mutation_allowed, - _ => LocalMutationIsAllowed::Yes + Some(field) + if { + self.mir.upvar_decls[field.index()].by_ref + } => + { + is_local_mutation_allowed + } + _ => LocalMutationIsAllowed::Yes, }; self.is_mutable(&proj.base, mode) @@ -1513,22 +1540,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // All other projections are owned by their base path, so mutable if // base path is mutable - ProjectionElem::Field(..) | - ProjectionElem::Index(..) | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Subslice { .. } | - ProjectionElem::Downcast(..) => { + ProjectionElem::Field(..) + | ProjectionElem::Index(..) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Downcast(..) => { if let Some(field) = self.is_upvar_field_projection(place) { let decl = &self.mir.upvar_decls[field.index()]; - debug!("decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}", - decl, is_local_mutation_allowed, place); + debug!( + "decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}", + decl, + is_local_mutation_allowed, + place + ); match (decl.mutability, is_local_mutation_allowed) { - (Mutability::Not, LocalMutationIsAllowed::No) | - (Mutability::Not, LocalMutationIsAllowed::ExceptUpvars) - => Err(place), - (Mutability::Not, LocalMutationIsAllowed::Yes) | - (Mutability::Mut, _) => + (Mutability::Not, LocalMutationIsAllowed::No) + | (Mutability::Not, LocalMutationIsAllowed::ExceptUpvars) => { + Err(place) + } + (Mutability::Not, LocalMutationIsAllowed::Yes) + | (Mutability::Mut, _) => { self.is_mutable(&proj.base, is_local_mutation_allowed) + } } } else { self.is_mutable(&proj.base, is_local_mutation_allowed) @@ -1593,11 +1626,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Given that the bases of `elem1` and `elem2` are always either equal // or disjoint (and have the same type!), return the overlap situation // between `elem1` and `elem2`. - fn place_element_conflict(&self, - elem1: &Place<'tcx>, - elem2: &Place<'tcx>) - -> Overlap - { + fn place_element_conflict(&self, elem1: &Place<'tcx>, elem2: &Place<'tcx>) -> Overlap { match (elem1, elem2) { (Place::Local(l1), Place::Local(l2)) => { if l1 == l2 { @@ -1623,8 +1652,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Overlap::EqualOrDisjoint } } - (Place::Local(_), Place::Static(_)) | - (Place::Static(_), Place::Local(_)) => { + (Place::Local(_), Place::Static(_)) | (Place::Static(_), Place::Local(_)) => { debug!("place_element_conflict: DISJOINT-STATIC-LOCAL"); Overlap::Disjoint } @@ -1689,15 +1717,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Overlap::Disjoint } } - (ProjectionElem::Index(..), ProjectionElem::Index(..)) | - (ProjectionElem::Index(..), ProjectionElem::ConstantIndex { .. }) | - (ProjectionElem::Index(..), ProjectionElem::Subslice { .. }) | - (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Index(..)) | - (ProjectionElem::ConstantIndex { .. }, ProjectionElem::ConstantIndex { .. }) | - (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Subslice { .. }) | - (ProjectionElem::Subslice { .. }, ProjectionElem::Index(..)) | - (ProjectionElem::Subslice { .. }, ProjectionElem::ConstantIndex { .. }) | - (ProjectionElem::Subslice { .. }, ProjectionElem::Subslice { .. }) => { + (ProjectionElem::Index(..), ProjectionElem::Index(..)) + | (ProjectionElem::Index(..), ProjectionElem::ConstantIndex { .. }) + | (ProjectionElem::Index(..), ProjectionElem::Subslice { .. }) + | (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Index(..)) + | ( + ProjectionElem::ConstantIndex { .. }, + ProjectionElem::ConstantIndex { .. }, + ) + | (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Subslice { .. }) + | (ProjectionElem::Subslice { .. }, ProjectionElem::Index(..)) + | (ProjectionElem::Subslice { .. }, ProjectionElem::ConstantIndex { .. }) + | (ProjectionElem::Subslice { .. }, ProjectionElem::Subslice { .. }) => { // Array indexes (`a[0]` vs. `a[i]`). These can either be disjoint // (if the indexes differ) or equal (if they are the same), so this // is the recursive case that gives "equal *or* disjoint" its meaning. @@ -1714,41 +1745,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Overlap::EqualOrDisjoint } - (ProjectionElem::Deref, _) | - (ProjectionElem::Field(..), _) | - (ProjectionElem::Index(..), _) | - (ProjectionElem::ConstantIndex { .. }, _) | - (ProjectionElem::Subslice { .. }, _) | - (ProjectionElem::Downcast(..), _) => { - bug!("mismatched projections in place_element_conflict: {:?} and {:?}", - - elem1, elem2) - } + (ProjectionElem::Deref, _) + | (ProjectionElem::Field(..), _) + | (ProjectionElem::Index(..), _) + | (ProjectionElem::ConstantIndex { .. }, _) + | (ProjectionElem::Subslice { .. }, _) + | (ProjectionElem::Downcast(..), _) => bug!( + "mismatched projections in place_element_conflict: {:?} and {:?}", + elem1, + elem2 + ), } } - (Place::Projection(_), _) | - (_, Place::Projection(_)) => { - bug!("unexpected elements in place_element_conflict: {:?} and {:?}", - elem1, elem2) - } + (Place::Projection(_), _) | (_, Place::Projection(_)) => bug!( + "unexpected elements in place_element_conflict: {:?} and {:?}", + elem1, + elem2 + ), } } /// Returns whether an access of kind `access` to `access_place` conflicts with /// a borrow/full access to `borrow_place` (for deep accesses to mutable /// locations, this function is symmetric between `borrow_place` & `access_place`). - fn places_conflict(&mut self, - borrow_place: &Place<'tcx>, - access_place: &Place<'tcx>, - access: ShallowOrDeep) - -> bool - { - debug!("places_conflict({:?},{:?},{:?})", borrow_place, access_place, access); + fn places_conflict( + &mut self, + borrow_place: &Place<'tcx>, + access_place: &Place<'tcx>, + access: ShallowOrDeep, + ) -> bool { + debug!( + "places_conflict({:?},{:?},{:?})", + borrow_place, + access_place, + access + ); // Return all the prefixes of `place` in reverse order, including // downcasts. - fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>> - { + fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>> { let mut result = vec![]; let mut place = place; loop { @@ -1767,13 +1802,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let borrow_components = place_elements(borrow_place); let access_components = place_elements(access_place); - debug!("places_conflict: components {:?} / {:?}", - borrow_components, access_components); + debug!( + "places_conflict: components {:?} / {:?}", + borrow_components, + access_components + ); - let borrow_components = borrow_components.into_iter() - .map(Some).chain(iter::repeat(None)); - let access_components = access_components.into_iter() - .map(Some).chain(iter::repeat(None)); + let borrow_components = borrow_components + .into_iter() + .map(Some) + .chain(iter::repeat(None)); + let access_components = access_components + .into_iter() + .map(Some) + .chain(iter::repeat(None)); // The borrowck rules for proving disjointness are applied from the "root" of the // borrow forwards, iterating over "similar" projections in lockstep until // we can prove overlap one way or another. Essentially, we treat `Overlap` as @@ -1839,13 +1881,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let (base, elem) = match borrow_c { Place::Projection(box Projection { base, elem }) => (base, elem), - _ => bug!("place has no base?") + _ => bug!("place has no base?"), }; let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx); match (elem, &base_ty.sty, access) { - (_, _, Shallow(Some(ArtificialField::Discriminant))) | - (_, _, Shallow(Some(ArtificialField::ArrayLength))) => { + (_, _, Shallow(Some(ArtificialField::Discriminant))) + | (_, _, Shallow(Some(ArtificialField::ArrayLength))) => { // The discriminant and array length are like // additional fields on the type; they do not // overlap any existing data there. Furthermore, @@ -1866,9 +1908,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { debug!("places_conflict: shallow access behind ptr"); return false; } - (ProjectionElem::Deref, ty::TyRef(_, ty::TypeAndMut { - ty: _, mutbl: hir::MutImmutable - }), _) => { + ( + ProjectionElem::Deref, + ty::TyRef( + _, + ty::TypeAndMut { + ty: _, + mutbl: hir::MutImmutable, + }, + ), + _, + ) => { // the borrow goes through a dereference of a shared reference. // // I'm not sure why we are tracking these borrows - shared @@ -1878,12 +1928,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return false; } - (ProjectionElem::Deref, _, Deep) | - (ProjectionElem::Field { .. }, _, _) | - (ProjectionElem::Index { ..}, _, _) | - (ProjectionElem::ConstantIndex { .. }, _, _) | - (ProjectionElem::Subslice { .. }, _, _) | - (ProjectionElem::Downcast { .. }, _, _) => { + (ProjectionElem::Deref, _, Deep) + | (ProjectionElem::Field { .. }, _, _) + | (ProjectionElem::Index { .. }, _, _) + | (ProjectionElem::ConstantIndex { .. }, _, _) + | (ProjectionElem::Subslice { .. }, _, _) + | (ProjectionElem::Downcast { .. }, _, _) => { // Recursive case. This can still be disjoint on a // further iteration if this a shallow access and // there's a deref later on, e.g. a borrow @@ -1920,7 +1970,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return false; } } - } } } @@ -1963,7 +2012,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if self.places_conflict(&borrowed.borrowed_place, place, access) { let ctrl = op(self, i, borrowed); - if ctrl == Control::Break { return; } + if ctrl == Control::Break { + return; + } } } }