better test the special exception for reading through unique when things are shared
This commit is contained in:
parent
aa8f523df6
commit
a94e197105
3 changed files with 41 additions and 5 deletions
|
|
@ -167,13 +167,15 @@ impl<'tcx> Stack {
|
|||
behind a barrier", bor))
|
||||
}
|
||||
(BorStackItem::Uniq(itm_t), Borrow::Uniq(bor_t)) if itm_t == bor_t => {
|
||||
// Found matching unique item.
|
||||
// Found matching unique item. This is *always* required to use a `Uniq`:
|
||||
// The item must still be on the stack.
|
||||
if !is_write {
|
||||
// As a special case, if we are reading and since we *did* find the `Uniq`,
|
||||
// we try to pop less: We are happy with making a `Shr` or `Frz` active;
|
||||
// that one will not mind concurrent reads.
|
||||
// As a special case, if we are reading, let us see if it would be
|
||||
// beneficial to pretend we are a raw pointer instead. If
|
||||
// raw pointers are allowed to read while popping *less* than we
|
||||
// would have to pop, there is no reason not to let them do this.
|
||||
match self.reactivatable(Borrow::default(), is_write) {
|
||||
// If we got something better that `idx`, use that
|
||||
// If we got something better (popping less) that `idx`, use that
|
||||
Ok(None) => return Ok(None),
|
||||
Ok(Some(shr_idx)) if shr_idx <= idx => return Ok(Some(shr_idx)),
|
||||
// Otherwise just go on.
|
||||
|
|
@ -329,6 +331,8 @@ impl<'tcx> Stacks {
|
|||
)))
|
||||
}
|
||||
// Sometimes we also need to be frozen.
|
||||
// In this case we *both* push `Shr` and then freeze. This means that a `&mut`
|
||||
// to `*const` to `*mut` cast through `&` actually works.
|
||||
if frozen {
|
||||
// Even shared refs can have uniq tags (after transmute). That's not an error
|
||||
// but they do not get any freezing benefits.
|
||||
|
|
|
|||
9
tests/compile-fail/stacked_borrows/illegal_read4.rs
Normal file
9
tests/compile-fail/stacked_borrows/illegal_read4.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Using a raw invalidates derived `&mut` even for reading.
|
||||
fn main() {
|
||||
let mut x = 2;
|
||||
let xref1 = &mut x;
|
||||
let xraw = xref1 as *mut _;
|
||||
let xref2 = unsafe { &mut *xraw };
|
||||
let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
|
||||
let _illegal = *xref2; //~ ERROR does not exist on the stack
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ fn main() {
|
|||
ref_raw_int_raw();
|
||||
mut_shr_raw();
|
||||
mut_raw_then_mut_shr();
|
||||
mut_raw_mut();
|
||||
}
|
||||
|
||||
// Deref a raw ptr to access a field of a large struct, where the field
|
||||
|
|
@ -76,3 +77,25 @@ fn mut_raw_then_mut_shr() {
|
|||
}
|
||||
assert_eq!(x, 4);
|
||||
}
|
||||
|
||||
// Ensure that if we derive from a mut a raw, and then from that a mut,
|
||||
// and then read through the original mut, that does not invalidate the raw.
|
||||
// This shows that the read-exception for `&mut` applies even if the `Shr` item
|
||||
// on the stack is not at the top.
|
||||
fn mut_raw_mut() {
|
||||
let mut x = 2;
|
||||
{
|
||||
let xref1 = &mut x;
|
||||
let xraw = xref1 as *mut _;
|
||||
let _xref2 = unsafe { &mut *xraw };
|
||||
let _val = *xref1;
|
||||
unsafe { *xraw = 4; }
|
||||
// we can now use both xraw and xref1, for reading
|
||||
assert_eq!(*xref1, 4);
|
||||
assert_eq!(unsafe { *xraw }, 4);
|
||||
assert_eq!(*xref1, 4);
|
||||
assert_eq!(unsafe { *xraw }, 4);
|
||||
// we cannot use xref2; see `compile-fail/stacked-borows/illegal_read4.rs`
|
||||
}
|
||||
assert_eq!(x, 4);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue