Skip to content

Commit

Permalink
Fix all build errors
Browse files Browse the repository at this point in the history
  • Loading branch information
zakarumych committed Nov 8, 2024
1 parent f937b96 commit 627c5de
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 86 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ serde = { version = "1.0", optional = true }

[workspace]
members = ["tests"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(no_global_oom_handling)',
] }
27 changes: 16 additions & 11 deletions src/stable/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ use core::task::{Context, Poll};

use super::alloc::{AllocError, Allocator, Global, Layout};
use super::raw_vec::RawVec;
use super::unique::Unique;
#[cfg(not(no_global_oom_handling))]
use super::vec::Vec;
#[cfg(not(no_global_oom_handling))]
Expand All @@ -173,7 +174,7 @@ use alloc_crate::alloc::handle_alloc_error;
/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
pub struct Box<T: ?Sized, A: Allocator = Global>(NonNull<T>, A);
pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A);

// Safety: Box owns both T and A, so sending is safe if
// sending is safe for T and A.
Expand Down Expand Up @@ -585,7 +586,11 @@ impl<T, A: Allocator> Box<T, A> {
pub fn into_inner(boxed: Self) -> T {
let ptr = boxed.0;
let unboxed = unsafe { ptr.as_ptr().read() };
unsafe { boxed.1.deallocate(ptr.cast(), Layout::new::<T>()) };
unsafe {
boxed
.1
.deallocate(ptr.as_non_null_ptr().cast(), Layout::new::<T>())
};
unboxed
}
}
Expand Down Expand Up @@ -885,8 +890,8 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
/// ```
#[inline(always)]
pub unsafe fn assume_init(self) -> Box<T, A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
unsafe { Box::from_raw_in(raw as *mut T, alloc) }
let (raw, alloc) = Self::into_raw_with_allocator(self);
unsafe { Box::<T, A>::from_raw_in(raw as *mut T, alloc) }
}

/// Writes the value and converts to `Box<T, A>`.
Expand Down Expand Up @@ -958,8 +963,8 @@ impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {
/// ```
#[inline(always)]
pub unsafe fn assume_init(self) -> Box<[T], A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
unsafe { Box::from_raw_in(raw as *mut [T], alloc) }
let (raw, alloc) = Self::into_raw_with_allocator(self);
unsafe { Box::<[T], A>::from_raw_in(raw as *mut [T], alloc) }
}
}

Expand Down Expand Up @@ -1060,7 +1065,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// [`Layout`]: crate::Layout
#[inline(always)]
pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
Box(unsafe { NonNull::new_unchecked(raw) }, alloc)
Box(unsafe { Unique::new_unchecked(raw) }, alloc)
}

/// Consumes the `Box`, returning a wrapped raw pointer.
Expand Down Expand Up @@ -1271,7 +1276,7 @@ impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
let layout = Layout::for_value::<T>(&**self);
unsafe {
ptr::drop_in_place(self.0.as_mut());
self.1.deallocate(self.0.cast(), layout);
self.1.deallocate(self.0.as_non_null_ptr().cast(), layout);
}
}
}
Expand All @@ -1289,17 +1294,17 @@ impl<T, A: Allocator + Default> Default for Box<[T], A> {
#[inline(always)]
fn default() -> Self {
let ptr: NonNull<[T]> = NonNull::<[T; 0]>::dangling();
Box(ptr, A::default())
Box(unsafe { Unique::new_unchecked(ptr.as_ptr()) }, A::default())
}
}

impl<A: Allocator + Default> Default for Box<str, A> {
#[inline(always)]
fn default() -> Self {
// SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
let ptr: NonNull<str> = unsafe {
let ptr: Unique<str> = unsafe {
let bytes: NonNull<[u8]> = NonNull::<[u8; 0]>::dangling();
NonNull::new_unchecked(bytes.as_ptr() as *mut str)
Unique::new_unchecked(bytes.as_ptr() as *mut str)
};
Box(ptr, A::default())
}
Expand Down
16 changes: 10 additions & 6 deletions src/stable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,29 @@ mod macros;
#[cfg(feature = "alloc")]
mod slice;

#[cfg(feature = "alloc")]
mod unique;

/// Allows turning a [`Box<T: Sized, A>`][boxed::Box] into a [`Box<U: ?Sized, A>`][boxed::Box] where `T` can be unsizing-coerced into a `U`.
///
///
/// This is the only way to create an `allocator_api2::boxed::Box` of an unsized type on stable.
///
///
/// With the standard library's `alloc::boxed::Box`, this is done automatically using the unstable unsize traits, but this crate's Box
/// can't take advantage of that machinery on stable. So, we need to use type inference and the fact that you *can*
/// still coerce the inner pointer of a box to get the compiler to help us unsize it using this macro.
///
///
/// # Example
///
///
/// ```
/// use allocator_api2::unsize_box;
/// use allocator_api2::boxed::Box;
/// use core::any::Any;
///
///
/// let sized_box: Box<u64> = Box::new(0);
/// let unsized_box: Box<dyn Any> = unsize_box!(sized_box);
/// ```
#[macro_export]
#[cfg(feature = "alloc")]
macro_rules! unsize_box {( $boxed:expr $(,)? ) => ({
let (ptr, allocator) = ::allocator_api2::boxed::Box::into_raw_with_allocator($boxed);
// we don't want to allow casting to arbitrary type U, but we do want to allow unsize coercion to happen.
Expand All @@ -49,7 +53,7 @@ macro_rules! unsize_box {( $boxed:expr $(,)? ) => ({
// assign its result to.
let ptr: *mut _ = ptr;
// SAFETY: see above for why ptr's type can only be something that can be safely coerced.
// also, ptr just came from a properly allocated box in the same allocator.
// also, ptr just came from a properly allocated box in the same allocator.
unsafe {
::allocator_api2::boxed::Box::from_raw_in(ptr, allocator)
}
Expand Down
2 changes: 1 addition & 1 deletion src/stable/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl<T, A: Allocator> RawVec<T, A> {
let me = ManuallyDrop::new(self);
unsafe {
let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
Box::from_raw_in(slice, ptr::read(&me.alloc))
Box::<[MaybeUninit<T>], A>::from_raw_in(slice, ptr::read(&me.alloc))
}
}

Expand Down
106 changes: 106 additions & 0 deletions src/stable/unique.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
///
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
/// the kind of strong aliasing guarantees an instance of `T` can expect:
/// the referent of the pointer should not be modified without a unique path to
/// its owning Unique.
///
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
/// consider using `NonNull`, which has weaker semantics.
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
/// However the pointer may still dangle if it isn't dereferenced.
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
#[repr(transparent)]
pub(crate) struct Unique<T: ?Sized> {
pointer: NonNull<T>,
_marker: PhantomData<T>,
}

/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
unsafe impl<T: Send + ?Sized> Send for Unique<T> {}

/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}

impl<T: ?Sized> Unique<T> {
/// Creates a new `Unique`.
///
/// # Safety
///
/// `ptr` must be non-null.
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
// SAFETY: the caller must guarantee that `ptr` is non-null.
unsafe {
Unique {
pointer: NonNull::new_unchecked(ptr),
_marker: PhantomData,
}
}
}

/// Acquires the underlying `*mut` pointer.
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub const fn as_ptr(self) -> *mut T {
self.pointer.as_ptr()
}

/// Acquires the underlying `*mut` pointer.
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub const fn as_non_null_ptr(self) -> NonNull<T> {
self.pointer
}

/// Dereferences the content.
///
/// The resulting lifetime is bound to self so this behaves "as if"
/// it were actually an instance of T that is getting borrowed. If a longer
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
#[must_use]
#[inline]
pub const unsafe fn as_ref(&self) -> &T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { self.pointer.as_ref() }
}

/// Mutably dereferences the content.
///
/// The resulting lifetime is bound to self so this behaves "as if"
/// it were actually an instance of T that is getting borrowed. If a longer
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
#[must_use]
#[inline]
pub unsafe fn as_mut(&mut self) -> &mut T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a mutable reference.
unsafe { self.pointer.as_mut() }
}
}

impl<T: ?Sized> Clone for Unique<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}

impl<T: ?Sized> Copy for Unique<T> {}

use core::{marker::PhantomData, ptr::NonNull};
7 changes: 0 additions & 7 deletions src/stable/vec/into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,6 @@ impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {}

impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}

#[doc(hidden)]
pub trait NonDrop {}

// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
// and thus we can't implement drop-handling
impl<T: Copy> NonDrop for T {}

#[cfg(not(no_global_oom_handling))]
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
fn clone(&self) -> Self {
Expand Down
64 changes: 4 additions & 60 deletions src/stable/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use core::iter;
use core::iter::FromIterator;
use core::marker::PhantomData;
use core::mem::{self, size_of, ManuallyDrop, MaybeUninit};
use core::ops::{self, Bound, Index, IndexMut, Range, RangeBounds};
use core::ops::{self, Bound, Index, IndexMut, RangeBounds};
use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};

Expand Down Expand Up @@ -900,7 +900,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// # Examples
///
/// ```
/// use std::collections::TryReserveError;
/// use allocator_api2::collections::TryReserveError;
///
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
/// let mut output = Vec::new();
Expand Down Expand Up @@ -943,7 +943,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// # Examples
///
/// ```
/// use std::collections::TryReserveError;
/// use allocator_api2::collections::TryReserveError;
///
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
/// let mut output = Vec::new();
Expand Down Expand Up @@ -1049,7 +1049,7 @@ impl<T, A: Allocator> Vec<T, A> {
let me = ManuallyDrop::new(self);
let buf = ptr::read(&me.buf);
let len = me.len();
buf.into_box(len).assume_init()
Box::<[mem::MaybeUninit<T>], A>::assume_init(buf.into_box(len))
}
}

Expand Down Expand Up @@ -2545,62 +2545,6 @@ impl<T: PartialEq, A: Allocator> Vec<T, A> {
}
}

trait ExtendFromWithinSpec {
/// # Safety
///
/// - `src` needs to be valid index
/// - `self.capacity() - self.len()` must be `>= src.len()`
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>);
}

// impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
// default unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
// // SAFETY:
// // - len is increased only after initializing elements
// let (this, spare, len) = unsafe { self.split_at_spare_mut_with_len() };

// // SAFETY:
// // - caller guarantees that src is a valid index
// let to_clone = unsafe { this.get_unchecked(src) };

// iter::zip(to_clone, spare)
// .map(|(src, dst)| dst.write(src.clone()))
// // Note:
// // - Element was just initialized with `MaybeUninit::write`, so it's ok to increase len
// // - len is increased after each element to prevent leaks (see issue #82533)
// .for_each(|_| *len += 1);
// }
// }

impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
#[inline(always)]
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
let count = src.len();
{
let (init, spare) = self.split_at_spare_mut();

// SAFETY:
// - caller guarantees that `src` is a valid index
let source = unsafe { init.get_unchecked(src) };

// SAFETY:
// - Both pointers are created from unique slice references (`&mut [_]`)
// so they are valid and do not overlap.
// - Elements are :Copy so it's OK to copy them, without doing
// anything with the original values
// - `count` is equal to the len of `source`, so source is valid for
// `count` reads
// - `.reserve(count)` guarantees that `spare.len() >= count` so spare
// is valid for `count` writes
unsafe { ptr::copy_nonoverlapping(source.as_ptr(), spare.as_mut_ptr() as _, count) };
}

// SAFETY:
// - The elements were just initialized by `copy_nonoverlapping`
self.len += count;
}
}

////////////////////////////////////////////////////////////////////////////////
// Common trait implementations for Vec
////////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 0 additions & 1 deletion tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![cfg_attr(feature = "nightly", feature(allocator_api))]
#![cfg(not(no_global_oom_handling))]

use std::alloc::Layout;

Expand Down

0 comments on commit 627c5de

Please sign in to comment.