Skip to content

Commit 8153449

Browse files
committed
rename RefKind to UsageKind, because it not only used for references now
1 parent 478f137 commit 8153449

17 files changed

+84
-66
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use mono_hash_map::MonoHashMap;
4848
use stacked_borrows::{EvalContextExt as StackedBorEvalContextExt};
4949

5050
// Used by priroda
51-
pub use stacked_borrows::{Borrow, Stacks, Mut as MutBorrow};
51+
pub use stacked_borrows::{Borrow, Stack, Stacks, Mut as MutBorrow, BorStackItem};
5252

5353
/// Insert rustc arguments at the beginning of the argument listthat miri wants to be
5454
/// set per default, for maximal validation power.

src/stacked_borrows.rs

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ impl Borrow {
6464
}
6565
}
6666

67+
impl Default for Borrow {
68+
fn default() -> Self {
69+
Borrow::Mut(Mut::Raw)
70+
}
71+
}
72+
6773
/// An item in the borrow stack
6874
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
6975
pub enum BorStackItem {
@@ -74,26 +80,33 @@ pub enum BorStackItem {
7480
FnBarrier(usize)
7581
}
7682

77-
impl Default for Borrow {
78-
fn default() -> Self {
79-
Borrow::Mut(Mut::Raw)
83+
impl BorStackItem {
84+
#[inline(always)]
85+
pub fn is_fn_barrier(self) -> bool {
86+
match self {
87+
BorStackItem::FnBarrier(_) => true,
88+
_ => false,
89+
}
8090
}
8191
}
8292

83-
/// What kind of reference are we talking about?
93+
/// What kind of usage of the pointer are we talking about?
8494
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
85-
pub enum RefKind {
86-
Mut,
87-
Shr,
95+
pub enum UsageKind {
96+
/// Write, or create &mut
97+
Write,
98+
/// Read, or create &
99+
Read,
100+
/// Create *
88101
Raw,
89102
}
90103

91-
impl From<Option<hir::Mutability>> for RefKind {
104+
impl From<Option<hir::Mutability>> for UsageKind {
92105
fn from(mutbl: Option<hir::Mutability>) -> Self {
93106
match mutbl {
94-
None => RefKind::Raw,
95-
Some(hir::MutMutable) => RefKind::Mut,
96-
Some(hir::MutImmutable) => RefKind::Shr,
107+
None => UsageKind::Raw,
108+
Some(hir::MutMutable) => UsageKind::Write,
109+
Some(hir::MutImmutable) => UsageKind::Read,
97110
}
98111
}
99112
}
@@ -112,7 +125,7 @@ impl State {
112125

113126
/// Extra per-location state
114127
#[derive(Clone, Debug)]
115-
struct Stack {
128+
pub struct Stack {
116129
borrows: Vec<BorStackItem>, // used as a stack
117130
frozen_since: Option<Timestamp>,
118131
}
@@ -143,17 +156,17 @@ pub struct Stacks {
143156
/// Core operations
144157
impl<'tcx> Stack {
145158
/// Check if `bor` could be activated by unfreezing and popping.
146-
/// `ref_kind` indicates whether this is being used to read/write (or, equivalently, to
159+
/// `usage` indicates whether this is being used to read/write (or, equivalently, to
147160
/// borrow as &/&mut), or to borrow as raw.
148161
/// Returns `Err` if the answer is "no"; otherwise the data says
149162
/// what needs to happen to activate this: `None` = nothing,
150163
/// `Some(n)` = unfreeze and make item `n` the top item of the stack.
151-
fn reactivatable(&self, bor: Borrow, ref_kind: RefKind) -> Result<Option<usize>, String> {
164+
fn reactivatable(&self, bor: Borrow, usage: UsageKind) -> Result<Option<usize>, String> {
152165
let mut_borrow = match bor {
153166
Borrow::Frz(since) =>
154167
// The only way to reactivate a `Frz` is if this is already frozen.
155168
return match self.frozen_since {
156-
_ if ref_kind == RefKind::Mut =>
169+
_ if usage == UsageKind::Write =>
157170
Err(format!("Using a shared borrow for mutation")),
158171
None =>
159172
Err(format!("Location should be frozen but it is not")),
@@ -163,10 +176,11 @@ impl<'tcx> Stack {
163176
Err(format!("Location should be frozen since {} but it is only frozen \
164177
since {}", since, loc)),
165178
},
166-
Borrow::Mut(Mut::Raw) if self.is_frozen() && ref_kind != RefKind::Mut =>
179+
Borrow::Mut(Mut::Raw) if self.is_frozen() && usage != UsageKind::Write =>
167180
// Non-mutating access with a raw from a frozen location is a special case: The
168181
// shared refs do not mind raw reads, and the raw itself does not assume any
169-
// exclusivity. So we do not even require there to be a raw on the stack.
182+
// exclusivity. So we do not even require there to be a raw on the stack,
183+
// the raw is instead "matched" by the fact that this location is frozen.
170184
// This does not break the assumption that an `&mut` we own is
171185
// exclusive for reads, because there we have the invariant that
172186
// the location is *not* frozen.
@@ -183,7 +197,7 @@ impl<'tcx> Stack {
183197
if loc == mut_borrow {
184198
// We found it! This is good to know.
185199
// Yet, maybe we do not really want to pop?
186-
if ref_kind == RefKind::Shr && self.is_frozen() {
200+
if usage == UsageKind::Read && self.is_frozen() {
187201
// Whoever had exclusive access to this location allowed it
188202
// to become frozen. That can only happen if they reborrowed
189203
// to a shared ref, at which point they gave up on exclusive access.
@@ -204,10 +218,10 @@ impl<'tcx> Stack {
204218
Err(format!("Mutable borrow-to-reactivate ({:?}) does not exist on the stack", mut_borrow))
205219
}
206220

207-
/// Reactive `bor` for this stack. `ref_kind` indicates whether this is being
221+
/// Reactive `bor` for this stack. `usage` indicates whether this is being
208222
/// used to read/write (or, equivalently, to borrow as &/&mut), or to borrow as raw.
209-
fn reactivate(&mut self, bor: Borrow, ref_kind: RefKind) -> EvalResult<'tcx> {
210-
let action = match self.reactivatable(bor, ref_kind) {
223+
fn reactivate(&mut self, bor: Borrow, usage: UsageKind) -> EvalResult<'tcx> {
224+
let action = match self.reactivatable(bor, usage) {
211225
Ok(action) => action,
212226
Err(err) => return err!(MachineError(err)),
213227
};
@@ -274,20 +288,20 @@ impl State {
274288

275289
/// Higher-level operations
276290
impl<'tcx> Stacks {
277-
/// The single most operation: Make sure that using `ptr` as `ref_kind` is okay,
291+
/// The single most operation: Make sure that using `ptr` as `usage` is okay,
278292
/// and if `new_bor` is present then make that the new current borrow.
279293
fn use_and_maybe_re_borrow(
280294
&self,
281295
ptr: Pointer<Borrow>,
282296
size: Size,
283-
ref_kind: RefKind,
297+
usage: UsageKind,
284298
new_bor: Option<Borrow>,
285299
) -> EvalResult<'tcx> {
286300
trace!("use_and_maybe_re_borrow of tag {:?} as {:?}, new {:?}: {:?}, size {}",
287-
ptr.tag, ref_kind, new_bor, ptr, size.bytes());
301+
ptr.tag, usage, new_bor, ptr, size.bytes());
288302
let mut stacks = self.stacks.borrow_mut();
289303
for stack in stacks.iter_mut(ptr.offset, size) {
290-
stack.reactivate(ptr.tag, ref_kind)?;
304+
stack.reactivate(ptr.tag, usage)?;
291305
if let Some(new_bor) = new_bor {
292306
stack.initiate(new_bor);
293307
}
@@ -303,7 +317,7 @@ impl<'tcx> Stacks {
303317
size: Size,
304318
) -> EvalResult<'tcx> {
305319
// Reads behave exactly like the first half of a reborrow-to-shr
306-
self.use_and_maybe_re_borrow(ptr, size, RefKind::Shr, None)
320+
self.use_and_maybe_re_borrow(ptr, size, UsageKind::Read, None)
307321
}
308322

309323
#[inline(always)]
@@ -313,7 +327,7 @@ impl<'tcx> Stacks {
313327
size: Size,
314328
) -> EvalResult<'tcx> {
315329
// Writes behave exactly like the first half of a reborrow-to-mut
316-
self.use_and_maybe_re_borrow(ptr, size, RefKind::Mut, None)
330+
self.use_and_maybe_re_borrow(ptr, size, UsageKind::Write, None)
317331
}
318332

319333
pub fn memory_deallocated(
@@ -322,7 +336,7 @@ impl<'tcx> Stacks {
322336
size: Size,
323337
) -> EvalResult<'tcx> {
324338
// This is like mutating
325-
self.use_and_maybe_re_borrow(ptr, size, RefKind::Mut, None)
339+
self.use_and_maybe_re_borrow(ptr, size, UsageKind::Write, None)
326340
// FIXME: Error out of there are any barriers?
327341
}
328342

@@ -346,7 +360,7 @@ pub trait EvalContextExt<'tcx> {
346360
ptr: Pointer<Borrow>,
347361
pointee_ty: Ty<'tcx>,
348362
size: Size,
349-
ref_kind: RefKind,
363+
usage: UsageKind,
350364
) -> EvalResult<'tcx, Borrow>;
351365

352366

@@ -355,7 +369,7 @@ pub trait EvalContextExt<'tcx> {
355369
ptr: Pointer<Borrow>,
356370
pointee_ty: Ty<'tcx>,
357371
size: Size,
358-
ref_kind: RefKind,
372+
usage: UsageKind,
359373
) -> EvalResult<'tcx, Borrow>;
360374

361375
fn tag_new_allocation(
@@ -378,12 +392,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
378392
ptr: Pointer<Borrow>,
379393
pointee_ty: Ty<'tcx>,
380394
size: Size,
381-
ref_kind: RefKind,
395+
usage: UsageKind,
382396
) -> EvalResult<'tcx, Borrow> {
383397
let time = self.machine.stacked_borrows.increment_clock();
384-
let new_bor = match ref_kind {
385-
RefKind::Mut => Borrow::Mut(Mut::Uniq(time)),
386-
RefKind::Shr =>
398+
let new_bor = match usage {
399+
UsageKind::Write => Borrow::Mut(Mut::Uniq(time)),
400+
UsageKind::Read =>
387401
// FIXME This does not do enough checking when only part of the data has
388402
// interior mutability. When the type is `(i32, Cell<i32>)`, we want the
389403
// first field to be frozen but not the second.
@@ -393,18 +407,18 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
393407
// Shared reference with interior mutability.
394408
Borrow::Mut(Mut::Raw)
395409
},
396-
RefKind::Raw => Borrow::Mut(Mut::Raw),
410+
UsageKind::Raw => Borrow::Mut(Mut::Raw),
397411
};
398412
trace!("tag_reference: Creating new reference ({:?}) for {:?} (pointee {}, size {}): {:?}",
399-
ref_kind, ptr, pointee_ty, size.bytes(), new_bor);
413+
usage, ptr, pointee_ty, size.bytes(), new_bor);
400414

401415
// Make sure this reference is not dangling or so
402416
self.memory().check_bounds(ptr, size, false)?;
403417

404418
// Update the stacks. We cannot use `get_mut` becuse this might be immutable
405419
// memory.
406420
let alloc = self.memory().get(ptr.alloc_id).expect("We checked that the ptr is fine!");
407-
alloc.extra.use_and_maybe_re_borrow(ptr, size, ref_kind, Some(new_bor))?;
421+
alloc.extra.use_and_maybe_re_borrow(ptr, size, usage, Some(new_bor))?;
408422

409423
Ok(new_bor)
410424
}
@@ -418,39 +432,39 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
418432
ptr: Pointer<Borrow>,
419433
pointee_ty: Ty<'tcx>,
420434
size: Size,
421-
ref_kind: RefKind,
435+
usage: UsageKind,
422436
) -> EvalResult<'tcx, Borrow> {
423437
trace!("tag_reference: Accessing reference ({:?}) for {:?} (pointee {}, size {})",
424-
ref_kind, ptr, pointee_ty, size.bytes());
438+
usage, ptr, pointee_ty, size.bytes());
425439
// In principle we should not have to do anything here. However, with transmutes involved,
426-
// it can happen that the tag of `ptr` does not actually match `ref_kind`, and we
440+
// it can happen that the tag of `ptr` does not actually match `usage`, and we
427441
// should adjust for that.
428442
// Notably, the compiler can introduce such transmutes by optimizing away `&[mut]*`.
429443
// That can transmute a raw ptr to a (shared/mut) ref, and a mut ref to a shared one.
430-
match (ref_kind, ptr.tag) {
431-
(RefKind::Raw, _) => {
444+
match (usage, ptr.tag) {
445+
(UsageKind::Raw, _) => {
432446
// Don't use the tag, this is a raw access! Even if there is a tag,
433447
// that means transmute happened and we ignore the tag.
434448
// Also don't do any further validation, this is raw after all.
435449
return Ok(Borrow::Mut(Mut::Raw));
436450
}
437-
(RefKind::Mut, Borrow::Mut(Mut::Uniq(_))) |
438-
(RefKind::Shr, Borrow::Frz(_)) |
439-
(RefKind::Shr, Borrow::Mut(Mut::Raw)) => {
451+
(UsageKind::Write, Borrow::Mut(Mut::Uniq(_))) |
452+
(UsageKind::Read, Borrow::Frz(_)) |
453+
(UsageKind::Read, Borrow::Mut(Mut::Raw)) => {
440454
// Expected combinations. Nothing to do.
441455
// FIXME: We probably shouldn't accept this if we got a raw shr without
442456
// interior mutability.
443457
}
444-
(RefKind::Mut, Borrow::Mut(Mut::Raw)) => {
458+
(UsageKind::Write, Borrow::Mut(Mut::Raw)) => {
445459
// Raw transmuted to mut ref. Keep this as raw access.
446460
// We cannot reborrow here; there might be a raw in `&(*var).1` where
447461
// `var` is an `&mut`. The other field of the struct might be already frozen,
448462
// also using `var`, and that would be okay.
449463
}
450-
(RefKind::Shr, Borrow::Mut(Mut::Uniq(_))) => {
464+
(UsageKind::Read, Borrow::Mut(Mut::Uniq(_))) => {
451465
// A mut got transmuted to shr. The mut borrow must be reactivatable.
452466
}
453-
(RefKind::Mut, Borrow::Frz(_)) => {
467+
(UsageKind::Write, Borrow::Frz(_)) => {
454468
// This is just invalid.
455469
// If we ever allow this, we have to consider what we do when a turn a
456470
// `Raw`-tagged `&mut` into a raw pointer pointing to a frozen location.
@@ -467,8 +481,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
467481
// We need `iter_mut` because `iter` would skip gaps!
468482
for stack in stacks.iter_mut(ptr.offset, size) {
469483
// Conservatively assume that we will only read.
470-
if let Err(err) = stack.reactivatable(ptr.tag, RefKind::Shr) {
471-
return err!(MachineError(format!("Encountered {:?} reference with non-reactivatable tag: {}", ref_kind, err)))
484+
if let Err(err) = stack.reactivatable(ptr.tag, UsageKind::Read) {
485+
return err!(MachineError(format!(
486+
"Encountered {} reference with non-reactivatable tag: {}",
487+
if usage == UsageKind::Write { "mutable" } else { "shared" },
488+
err
489+
)))
472490
}
473491
}
474492
// 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
@@ -11,5 +11,5 @@ fn main() {
1111
retarget(&mut target_alias, target);
1212
// now `target_alias` points to the same thing as `target`
1313
*target = 13;
14-
let _val = *target_alias; //~ ERROR Shr reference with non-reactivatable tag
14+
let _val = *target_alias; //~ ERROR reference with non-reactivatable tag
1515
}

tests/compile-fail/stacked_borrows/buggy_as_mut_slice.rs

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

tests/compile-fail/stacked_borrows/buggy_split_at_mut.rs

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

1313
(from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid"
14-
//~^ ERROR Mut reference with non-reactivatable tag
14+
//~^ ERROR reference with non-reactivatable tag
1515
from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
1616
}
1717
}

tests/compile-fail/stacked_borrows/illegal_read1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn main() {
77
let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
88
callee(xraw);
99
let _val = *xref; // ...but any use of raw will invalidate our ref.
10-
//~^ ERROR: Mut reference with non-reactivatable tag
10+
//~^ ERROR: mutable reference with non-reactivatable tag
1111
}
1212

1313
fn callee(xraw: *mut i32) {

tests/compile-fail/stacked_borrows/illegal_read2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn main() {
77
let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
88
callee(xraw);
99
let _val = *xref; // ...but any use of raw will invalidate our ref.
10-
//~^ ERROR: Mut reference with non-reactivatable tag
10+
//~^ ERROR: mutable reference with non-reactivatable tag
1111
}
1212

1313
fn callee(xraw: *mut i32) {

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
11+
let _x = *ref_; //~ ERROR reference with non-reactivatable tag
1212
}

tests/compile-fail/stacked_borrows/illegal_write5.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn main() {
77
let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
88
callee(xraw);
99
let _val = *xref; // ...but any use of raw will invalidate our ref.
10-
//~^ ERROR: Mut reference with non-reactivatable tag
10+
//~^ ERROR: reference with non-reactivatable tag
1111
}
1212

1313
fn callee(xraw: *mut i32) {

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
8+
let _val = *xref_in_mem; //~ ERROR mutable reference with non-reactivatable tag
99
}

0 commit comments

Comments
 (0)