Skip to content

Commit

Permalink
Auto merge of #201 - cuviper:safe-drain, r=Amanieu
Browse files Browse the repository at this point in the history
Make `RawTable::drain` safe

The documentation indicated a safety question of the lifetime, but there
is a lifetime parameter on `RawDrain` to ensure that. Also, the similar
`par_drain` is already a safe method.

I also adjusted the safety comments on `drain_iter_from`/`into_iter_from`.
The safety contract for these methods is really about the validity of
the given `RawIter` for this `RawTable`. Once that's established, the
lifetime is no longer a concern, since `RawDrain<'_, T>` has a borrow
and `RawIntoIter<T>` is a consuming owner.
  • Loading branch information
bors committed Sep 13, 2020
2 parents 0f38616 + a56db69 commit d26b37a
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 22 deletions.
7 changes: 2 additions & 5 deletions src/map.rs
Expand Up @@ -548,11 +548,8 @@ impl<K, V, S> HashMap<K, V, S> {
/// ```
#[cfg_attr(feature = "inline-more", inline)]
pub fn drain(&mut self) -> Drain<'_, K, V> {
// Here we tie the lifetime of self to the iter.
unsafe {
Drain {
inner: self.table.drain(),
}
Drain {
inner: self.table.drain(),
}
}

Expand Down
28 changes: 11 additions & 17 deletions src/raw/mod.rs
Expand Up @@ -1062,25 +1062,21 @@ impl<T> RawTable<T> {

/// Returns an iterator which removes all elements from the table without
/// freeing the memory.
///
/// It is up to the caller to ensure that the `RawTable` outlives the `RawDrain`.
/// Because we cannot make the `next` method unsafe on the `RawDrain`,
/// we have to make the `drain` method unsafe.
#[cfg_attr(feature = "inline-more", inline)]
pub unsafe fn drain(&mut self) -> RawDrain<'_, T> {
let iter = self.iter();
self.drain_iter_from(iter)
pub fn drain(&mut self) -> RawDrain<'_, T> {
unsafe {
let iter = self.iter();
self.drain_iter_from(iter)
}
}

/// Returns an iterator which removes all elements from the table without
/// freeing the memory.
///
/// It is up to the caller to ensure that the `RawTable` outlives the `RawDrain`.
/// Because we cannot make the `next` method unsafe on the `RawDrain`,
/// we have to make the `drain` method unsafe.
///
/// Iteration starts at the provided iterator's current location.
/// You must ensure that the iterator covers all items that remain in the table.
///
/// It is up to the caller to ensure that the iterator is valid for this
/// `RawTable` and covers all items that remain in the table.
#[cfg_attr(feature = "inline-more", inline)]
pub unsafe fn drain_iter_from(&mut self, iter: RawIter<T>) -> RawDrain<'_, T> {
debug_assert_eq!(iter.len(), self.len());
Expand All @@ -1094,12 +1090,10 @@ impl<T> RawTable<T> {

/// Returns an iterator which consumes all elements from the table.
///
/// It is up to the caller to ensure that the `RawTable` outlives the `RawIntoIter`.
/// Because we cannot make the `next` method unsafe on the `RawIntoIter`,
/// we have to make the `into_iter_from` method unsafe.
///
/// Iteration starts at the provided iterator's current location.
/// You must ensure that the iterator covers all items that remain in the table.
///
/// It is up to the caller to ensure that the iterator is valid for this
/// `RawTable` and covers all items that remain in the table.
pub unsafe fn into_iter_from(self, iter: RawIter<T>) -> RawIntoIter<T> {
debug_assert_eq!(iter.len(), self.len());

Expand Down

0 comments on commit d26b37a

Please sign in to comment.