Skip to content

Commit 5388037

Browse files
committed
remove code duplication by letting reactivatable() compute what reactivate() has to do
1 parent fe83ef3 commit 5388037

File tree

9 files changed

+47
-58
lines changed

9 files changed

+47
-58
lines changed

src/stacked_borrows.rs

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -137,75 +137,64 @@ impl<'tcx> Stack {
137137
}
138138

139139
/// Check if `bor` could be activated by unfreezing and popping.
140-
/// This should be in sync with `reactivate`!
141-
fn reactivatable(&self, bor: Borrow) -> bool {
142-
if self.check(bor) {
143-
return true;
144-
}
145-
146-
let acc_m = match bor {
147-
Borrow::Frz(_) => return false,
148-
Borrow::Mut(acc_m) => acc_m
149-
};
150-
// This is where we would unfreeze.
151-
for &itm in self.borrows.iter().rev() {
152-
match itm {
153-
BorStackItem::FnBarrier(_) => return false,
154-
BorStackItem::Mut(loc_m) => {
155-
if loc_m == acc_m { return true; }
156-
// Go on looking.
157-
}
158-
}
159-
}
160-
// Nothing to be found.
161-
false
162-
}
163-
164-
/// Reactive `bor` for this stack. If `force_mut` is set, we want to aggressively
165-
/// unfreeze this location (because we are about to mutate, so a frozen `Raw` is not okay).
166-
fn reactivate(&mut self, bor: Borrow, force_mut: bool) -> EvalResult<'tcx> {
140+
/// `force_mut` indicates whether being frozen is potentially acceptable.
141+
/// Returns `Err` if the answer is "no"; otherwise the data says
142+
/// what needs to happen to activate this: `None` = nothing,
143+
/// `Some(n)` = unfreeze and make item `n` the top item of the stack.
144+
fn reactivatable(&self, bor: Borrow, force_mut: bool) -> Result<Option<usize>, String> {
167145
// Unless mutation is bound to happen, do NOT change anything if `bor` is already active.
168146
// In particular, if it is a `Mut(Raw)` and we are frozen, this should be a NOP.
169147
if !force_mut && self.check(bor) {
170-
return Ok(());
148+
return Ok(None);
171149
}
172150

173151
let acc_m = match bor {
174152
Borrow::Frz(since) =>
175-
if force_mut {
176-
return err!(MachineError(format!("Using a shared borrow for mutation")))
153+
return Err(if force_mut {
154+
format!("Using a shared borrow for mutation")
177155
} else {
178-
return err!(MachineError(format!(
156+
format!(
179157
"Location should be frozen since {} but {}",
180158
since,
181159
match self.frozen_since {
182160
None => format!("it is not frozen at all"),
183161
Some(since) => format!("it is only frozen since {}", since),
184162
}
185-
)))
186-
}
187-
Borrow::Mut(acc_m) => acc_m,
163+
)
164+
}),
165+
Borrow::Mut(acc_m) => acc_m
188166
};
189-
// We definitely have to unfreeze this, even if we use the topmost item.
190-
if self.frozen_since.is_some() {
191-
trace!("reactivate: Unfreezing");
192-
}
193-
self.frozen_since = None;
194-
// Pop until we see the one we are looking for.
195-
while let Some(&itm) = self.borrows.last() {
167+
// This is where we would unfreeze.
168+
for (idx, &itm) in self.borrows.iter().enumerate().rev() {
196169
match itm {
197-
BorStackItem::FnBarrier(_) => {
198-
return err!(MachineError(format!("Trying to reactivate a borrow that lives behind a barrier")));
199-
}
170+
BorStackItem::FnBarrier(_) =>
171+
return Err(format!("Trying to reactivate a mutable borrow ({:?}) that lives behind a barrier", acc_m)),
200172
BorStackItem::Mut(loc_m) => {
201-
if loc_m == acc_m { return Ok(()); }
202-
trace!("reactivate: Popping {:?}", itm);
203-
self.borrows.pop();
173+
if loc_m == acc_m { return Ok(Some(idx)); }
204174
}
205175
}
206176
}
207177
// Nothing to be found.
208-
err!(MachineError(format!("Borrow-to-reactivate does not exist on the stack")))
178+
Err(format!("Mutable borrow-to-reactivate ({:?}) does not exist on the stack", acc_m))
179+
}
180+
181+
/// Reactive `bor` for this stack. If `force_mut` is set, we want to aggressively
182+
/// unfreeze this location (because we are about to mutate, so a frozen `Raw` is not okay).
183+
fn reactivate(&mut self, bor: Borrow, force_mut: bool) -> EvalResult<'tcx> {
184+
let action = match self.reactivatable(bor, force_mut) {
185+
Ok(action) => action,
186+
Err(err) => return err!(MachineError(err)),
187+
};
188+
189+
match action {
190+
None => {}, // nothing to do
191+
Some(top) => {
192+
self.frozen_since = None;
193+
self.borrows.truncate(top+1);
194+
}
195+
}
196+
197+
Ok(())
209198
}
210199

211200
/// Initiate `bor`; mostly this means freezing or pushing.
@@ -471,8 +460,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
471460
// be shared reborrows that we are about to invalidate with this access.
472461
// We cannot invalidate them aggressively here because the deref might also be
473462
// to just create more shared refs.
474-
if !stack.reactivatable(ptr.tag) {
475-
return err!(MachineError(format!("Encountered {:?} reference with non-reactivatable tag {:?}", ref_kind, ptr.tag)))
463+
if let Err(err) = stack.reactivatable(ptr.tag, /*force_mut*/false) {
464+
return err!(MachineError(format!("Encountered {:?} reference with non-reactivatable tag: {}", ref_kind, err)))
476465
}
477466
}
478467
// All is good.

tests/compile-fail/stacked_borrows/alias_through_mutation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ fn main() {
1414
retarget(&mut target_alias, target);
1515
// now `target_alias` points to the same thing as `target`
1616
*target = 13;
17-
let _val = *target_alias; //~ ERROR Shr reference with non-reactivatable tag Frz
17+
let _val = *target_alias; //~ ERROR Shr reference with non-reactivatable tag
1818
}

tests/compile-fail/stacked_borrows/buggy_as_mut_slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ fn main() {
1717
let v = vec![0,1,2];
1818
let v1 = safe::as_mut_slice(&v);
1919
let v2 = safe::as_mut_slice(&v);
20-
v1[1] = 5; //~ ERROR Mut reference with non-reactivatable tag Mut(Uniq
20+
v1[1] = 5; //~ ERROR Mut reference with non-reactivatable tag
2121
v1[1] = 6;
2222
}

tests/compile-fail/stacked_borrows/buggy_split_at_mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod safe {
1414
assert!(mid <= len);
1515

1616
(from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid"
17-
//~^ ERROR Mut reference with non-reactivatable tag Mut(Uniq
17+
//~^ ERROR Mut reference with non-reactivatable tag
1818
from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
1919
}
2020
}

tests/compile-fail/stacked_borrows/illegal_write1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ fn main() {
88
let target = Box::new(42); // has an implicit raw
99
let ref_ = &*target;
1010
evil(ref_); // invalidates shared ref, activates raw
11-
let _x = *ref_; //~ ERROR Shr reference with non-reactivatable tag Frz
11+
let _x = *ref_; //~ ERROR Shr reference with non-reactivatable tag
1212
}

tests/compile-fail/stacked_borrows/load_invalid_mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ fn main() {
55
let xref = unsafe { &mut *xraw };
66
let xref_in_mem = Box::new(xref);
77
let _val = *x; // invalidate xraw
8-
let _val = *xref_in_mem; //~ ERROR Mut reference with non-reactivatable tag Mut(Uniq
8+
let _val = *xref_in_mem; //~ ERROR Mut reference with non-reactivatable tag
99
}

tests/compile-fail/stacked_borrows/pass_invalid_mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ fn main() {
66
let xraw = x as *mut _;
77
let xref = unsafe { &mut *xraw };
88
let _val = *x; // invalidate xraw
9-
foo(xref); //~ ERROR Mut reference with non-reactivatable tag Mut(Uniq
9+
foo(xref); //~ ERROR Mut reference with non-reactivatable tag
1010
}

tests/compile-fail/stacked_borrows/return_invalid_mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ fn foo(x: &mut (i32, i32)) -> &mut i32 {
33
let xraw = x as *mut (i32, i32);
44
let ret = unsafe { &mut (*xraw).1 };
55
let _val = *x; // invalidate xraw and its children
6-
ret //~ ERROR Mut reference with non-reactivatable tag Mut(Uniq
6+
ret //~ ERROR Mut reference with non-reactivatable tag
77
}
88

99
fn main() {

tests/compile-fail/stacked_borrows/shared_confusion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn test(r: &mut RefCell<i32>) {
1313
}
1414
// Our old raw should be dead by now
1515
unsafe { *x_evil = 0; } // this falls back to some Raw higher up the stack
16-
*x_inner = 12; //~ ERROR Mut reference with non-reactivatable tag Mut(Uniq
16+
*x_inner = 12; //~ ERROR Mut reference with non-reactivatable tag
1717
}
1818

1919
fn main() {

0 commit comments

Comments
 (0)