From d1f8aece0d7f03bb7b54668f2d6139fba2e51ecd Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Sat, 22 Oct 2022 22:26:19 -0600
Subject: [PATCH] option_bucket: replace ptrs with unwrap_unchecked
---
option-bucket/src/lib.rs | 66 +++++++++++-----------------------------
1 file changed, 18 insertions(+), 48 deletions(-)
diff --git a/option-bucket/src/lib.rs b/option-bucket/src/lib.rs
index e3d77a4..0133518 100644
--- a/option-bucket/src/lib.rs
+++ b/option-bucket/src/lib.rs
@@ -75,8 +75,9 @@
//!
//! # Unsafe Usage
//!
-//! This crate uses `unsafe` to dereference raw pointers and to
-//! obtain mutable references to the inner value of `Some`s.
+//! This crate uses `unwrap_unchecked` to obtain
+//! mutable references to the inner value of `Some`s,
+//! and to skip `drop` when overwriting `None`s.
#![no_std]
#![deny(missing_docs)]
@@ -121,8 +122,6 @@
// `clippy::pedantic` exceptions
#![allow(clippy::should_implement_trait, clippy::must_use_candidate)]
-use core::marker::PhantomData;
-
/// Abstraction for an [`&mut Option`][Option] that's known to be [`Some`].
///
/// # Size
@@ -131,11 +130,7 @@ use core::marker::PhantomData;
/// twice the size of `&mut Option`. One points to the
/// value inside, and the other points to the `Option` itself.
pub struct SomeBucket<'a, T> {
- /// Pointer to the `Option::Some`
- outer: *mut Option,
- /// Pointer to the value within the `Option::Some`
- inner: *mut T,
- _life: PhantomData<&'a mut Option>,
+ outer: &'a mut Option,
}
impl<'a, T> SomeBucket<'a, T> {
/// Creates a new [`SomeBucket`], without checking that
@@ -153,16 +148,7 @@ impl<'a, T> SomeBucket<'a, T> {
"Undefined Behavior: `None` value passed to `SomeBucket::new_unchecked`."
);
- let outer: *mut Option = opt;
-
- // SAFETY: Caller guarantees that `opt` is `Some`
- let inner: *mut T = unsafe { opt.as_mut().unwrap_unchecked() };
-
- SomeBucket {
- outer,
- inner,
- _life: PhantomData,
- }
+ SomeBucket { outer: opt }
}
/// Creates a new [`SomeBucket`]. Returns `Some(SomeBucket)`
@@ -194,12 +180,9 @@ impl<'a, T> SomeBucket<'a, T> {
/// assert_eq!(length, 13);
/// ```
pub fn as_ref(&self) -> &T {
- // SAFETY:
- // `inner` is a valid pointer to `T`, as guaranteed
- // by invariants of `new`. This can not alias a
- // mutable reference, because any way to produce one
- // requires a unique reference to self
- unsafe { &(*self.inner) }
+ // SAFETY: `outer` is guaranteed to be `Some`
+ // by the invariants of `new_unchecked`
+ unsafe { self.outer.as_ref().unwrap_unchecked() }
}
/// Converts from `&mut Option::Some` to `&mut T`,
@@ -217,12 +200,9 @@ impl<'a, T> SomeBucket<'a, T> {
/// assert_eq!(some.as_ref(), "Hello, world! Happy to be here.");
/// ```
pub fn as_mut(&mut self) -> &mut T {
- // SAFETY:
- // `inner` is a valid pointer to `T`, as guaranteed
- // be invariants of `new`. This can not alias another
- // mutable reference, because any way to produce one
- // requires a unique reference to self
- unsafe { &mut (*self.inner) }
+ // SAFETY: `outer` is guaranteed to be `Some`
+ // by the invariants of `new_unchecked`
+ unsafe { self.outer.as_mut().unwrap_unchecked() }
}
/// Converts from `&mut Option::Some` to `&mut T`,
@@ -252,12 +232,9 @@ impl<'a, T> SomeBucket<'a, T> {
/// some.as_ref();
/// ```
pub fn into_mut(self) -> &'a mut T {
- // SAFETY:
- // `inner` is a valid pointer to `T`, as guaranteed
- // be invariants of `new`. This can not alias another
- // mutable reference, because any way to produce one
- // requires a unique reference to self
- unsafe { &mut (*self.inner) }
+ // SAFETY: `outer` is guaranteed to be `Some`
+ // by the invariants of `new_unchecked`
+ unsafe { self.outer.as_mut().unwrap_unchecked() }
}
/// Sets the value in the `Option::Some`, and returns
@@ -293,16 +270,9 @@ impl<'a, T> SomeBucket<'a, T> {
/// assert_eq!(y, vec![1, 2]);
/// ```
pub fn take(self) -> T {
- // SAFETY:
- // `inner` is a valid pointer to `T`, as guaranteed
- // be invariants of `new`. We set the original
- // `Option` to `None`, ensuring that the original
- // copy of the value will not be double-dropped
- unsafe {
- let value = self.inner.read();
- self.outer.write(None);
- value
- }
+ // SAFETY: `outer` is guaranteed to be `Some`
+ // by the invariants of `new_unchecked`
+ unsafe { self.outer.take().unwrap_unchecked() }
}
}
@@ -362,7 +332,7 @@ impl<'a, T> NoneBucket<'a, T> {
/// assert_eq!(opt.unwrap(), 3);
/// ```
pub fn insert(self, value: T) -> &'a mut T {
- // SAFETY: `outer` is `None`, so there is no old value to leak
+ // SAFETY: `outer` is `None`, so there is no old value to `drop`
unsafe {
let outer: *mut Option = self.outer;
outer.write(Some(value));