Skip to content

Commit

Permalink
Allow nested two phase borrows
Browse files Browse the repository at this point in the history
  • Loading branch information
xFrednet committed Apr 26, 2024
1 parent 40bd195 commit 839da51
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 12 deletions.
25 changes: 13 additions & 12 deletions clippy_lints/src/borrow_pats/owned/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct StateInfo<'tcx> {
/// use an option and cry when it fails.
///
/// See: https://rustc-dev-guide.rust-lang.org/borrow_check/two_phase_borrows.html
phase_borrow: Option<(Local, Place<'tcx>)>,
phase_borrow: Vec<(Local, Place<'tcx>)>,
}

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Default)]
Expand Down Expand Up @@ -70,7 +70,7 @@ impl<'tcx> StateInfo<'tcx> {
pub fn kill_local(&mut self, local: Local) {
self.anons.remove(&local);
self.borrows.remove(&local);
self.phase_borrow.take_if(|(phase_local, _place)| *phase_local == local);
self.phase_borrow.retain(|(phase_local, _place)| *phase_local != local);
}

/// This tries to remove the given place from the known anons that hold this value.
Expand All @@ -90,7 +90,7 @@ impl<'tcx> StateInfo<'tcx> {
pub fn clear(&mut self) {
self.anons.clear();
self.borrows.clear();
self.phase_borrow = None;
self.phase_borrow.clear();

self.state = State::None;
}
Expand All @@ -107,8 +107,10 @@ impl<'tcx> StateInfo<'tcx> {
self.update_bros(broker, kind.mutability(), info);

if matches!(kind, BorrowKind::Shared)
&& let Some((_loc, phase_place)) = self.phase_borrow
&& info.places_conflict(phase_place, broker)
&& self
.phase_borrow
.iter()
.any(|(_loc, phase_place)| info.places_conflict(*phase_place, broker))
{
pats.insert(OwnedPat::TwoPhasedBorrow);
info.stats.borrow_mut().two_phase_borrows += 1;
Expand All @@ -130,8 +132,7 @@ impl<'tcx> StateInfo<'tcx> {
if !is_named {
assert!(borrow.just_local());
if kind.allows_two_phase_borrow() {
let old = self.phase_borrow.replace((borrow.local, broker));
assert_eq!(old, None);
self.phase_borrow.push((borrow.local, broker));
} else {
self.borrows.insert(borrow.local, (broker, kind.mutability(), bro_kind));
}
Expand Down Expand Up @@ -174,7 +175,7 @@ impl<'tcx> StateInfo<'tcx> {
pub fn has_bro(&mut self, anon: &Place<'_>) -> Option<(Place<'tcx>, Mutability, BroKind)> {
assert!(anon.just_local());

if let Some((_loc, place)) = self.phase_borrow.as_ref().filter(|(local, _place)| *local == anon.local) {
if let Some((_loc, place)) = self.phase_borrow.iter().find(|(local, _place)| *local == anon.local) {
// TwoPhaseBorrows are always mutable
Some((*place, Mutability::Mut, BroKind::Anon))
} else {
Expand Down Expand Up @@ -213,10 +214,10 @@ impl<'a, 'tcx> MyStateInfo<super::OwnedAnalysis<'a, 'tcx>> for StateInfo<'tcx> {
self.borrows.extend(other.borrows.iter());
changed |= (self.anons.len() != anons_previous_len) || (self.borrows.len() != anon_bros_previous_len);

assert!(!(self.phase_borrow.is_some() && other.phase_borrow.is_some()));
if let Some(data) = other.phase_borrow {
self.phase_borrow = Some(data);
changed = true;
{
let phase_borrow_len = self.phase_borrow.len();
self.phase_borrow.extend(other.phase_borrow.iter());
changed |= self.phase_borrow.len() != phase_borrow_len;
}

// if let Some(bb_a) = self.assignments.last().copied()
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/thesis/pass/owned_borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ fn two_phase_borrow_2(mut num: usize, mut vec: Vec<usize>) {
})
}

#[warn(clippy::borrow_pats)]
fn nested_two_phase_borrow(mut vecs: NestedVecs) {
vecs.a.push({
vecs.b.push(vecs.a.len());
vecs.b.len()
});
}

struct NestedVecs {
a: Vec<usize>,
b: Vec<usize>,
}

fn take_1_loan(_: &String) {}
fn take_2_loan(_: &String, _: &String) {}
fn take_1_mut_loan(_: &String) {}
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/thesis/pass/owned_borrows.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@
- vec : (Mutable , Owned , Argument, NonCopy, Drop , UserDef ) {TempBorrow, TempBorrowMut, TwoPhasedBorrow}
- Body: Output(Unit) , NotConst , Safe , Sync , Free {HasAnonBorrow}

# "nested_two_phase_borrow"
- vecs : (Mutable , Owned , Argument, NonCopy, Drop , UserDef ) {TempBorrow, TempBorrowMut, TwoPhasedBorrow}
- Body: Output(Unit) , NotConst , Safe , Sync , Free {HasAnonBorrow}

0 comments on commit 839da51

Please sign in to comment.