Skip to content

Commit 32b9f78

Browse files
authored
Rollup merge of rust-lang#56161 - RalfJung:vecdeque-stacked-borrows, r=SimonSapin
VecDeque: fix for stacked borrows `VecDeque` violates a version of stacked borrows where creating a shared reference is not enough to make a location *mutably accessible* from raw pointers (and I think that is the version we want). There are two problems: * Creating a `NonNull<T>` from `&mut T` goes through `&T` (inferred for a `_`), then `*const T`, then `NonNull<T>`. That means in this stricter version of Stacked Borrows, we cannot actually write to such a `NonNull` because it was created from a shared reference! This PR fixes that by going from `&mut T` to `*mut T` to `*const T`. * `VecDeque::drain` creates the `Drain` struct by *first* creating a `NonNull` from `self` (which is an `&mut VecDeque`), and *then* calling `self.buffer_as_mut_slice()`. The latter reborrows `self`, asserting that `self` is currently the unique pointer to access this `VecDeque`, and hence invalidating the `NonNull` that was created earlier. This PR fixes that by instead using `self.buffer_as_slice()`, which only performs read accesses and creates only shared references, meaning the raw pointer (`NonNull`) remains valid. It is possible that other methods on `VecDeque` do something similar, miri's test coverage of `VecDeque` is sparse to say the least. Cc @nikomatsakis @gankro
2 parents ae3833d + feb775c commit 32b9f78

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

src/liballoc/collections/vec_deque.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,10 @@ impl<T> VecDeque<T> {
10261026
iter: Iter {
10271027
tail: drain_tail,
10281028
head: drain_head,
1029-
ring: unsafe { self.buffer_as_mut_slice() },
1029+
// Crucially, we only create shared references from `self` here and read from
1030+
// it. We do not write to `self` nor reborrow to a mutable reference.
1031+
// Hence the raw pointer we created above, for `deque`, remains valid.
1032+
ring: unsafe { self.buffer_as_slice() },
10301033
},
10311034
}
10321035
}

src/libcore/ptr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2848,14 +2848,14 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> {
28482848
#[unstable(feature = "ptr_internals", issue = "0")]
28492849
impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
28502850
fn from(reference: &'a mut T) -> Self {
2851-
Unique { pointer: unsafe { NonZero(reference as _) }, _marker: PhantomData }
2851+
Unique { pointer: unsafe { NonZero(reference as *mut T) }, _marker: PhantomData }
28522852
}
28532853
}
28542854

28552855
#[unstable(feature = "ptr_internals", issue = "0")]
28562856
impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
28572857
fn from(reference: &'a T) -> Self {
2858-
Unique { pointer: unsafe { NonZero(reference as _) }, _marker: PhantomData }
2858+
Unique { pointer: unsafe { NonZero(reference as *const T) }, _marker: PhantomData }
28592859
}
28602860
}
28612861

@@ -3058,14 +3058,14 @@ impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
30583058
impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
30593059
#[inline]
30603060
fn from(reference: &'a mut T) -> Self {
3061-
NonNull { pointer: unsafe { NonZero(reference as _) } }
3061+
NonNull { pointer: unsafe { NonZero(reference as *mut T) } }
30623062
}
30633063
}
30643064

30653065
#[stable(feature = "nonnull", since = "1.25.0")]
30663066
impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
30673067
#[inline]
30683068
fn from(reference: &'a T) -> Self {
3069-
NonNull { pointer: unsafe { NonZero(reference as _) } }
3069+
NonNull { pointer: unsafe { NonZero(reference as *const T) } }
30703070
}
30713071
}

0 commit comments

Comments
 (0)