Skip to content

Commit

Permalink
Undo NonZero length optimisation to fix ZST usage
Browse files Browse the repository at this point in the history
  • Loading branch information
GnomedDev committed Dec 2, 2024
1 parent 30387c8 commit 3b45676
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 36 deletions.
42 changes: 6 additions & 36 deletions src/array.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
use core::{fmt::Debug, hash::Hash, mem::ManuallyDrop, ptr::NonNull};

use crate::length::{InvalidLength, NonZero, SmallLen, ValidLength};
use crate::length::{InvalidLength, SmallLen, ValidLength};

#[cold]
fn truncate_vec<T>(err: InvalidLength<T>, max_len: usize) -> Vec<T> {
Expand All @@ -16,7 +16,7 @@ fn truncate_vec<T>(err: InvalidLength<T>, max_len: usize) -> Vec<T> {
#[repr(packed)]
pub struct FixedArray<T, LenT: ValidLength = SmallLen> {
ptr: NonNull<T>,
len: LenT::NonZero,
len: LenT,
}

impl<T, LenT: ValidLength> FixedArray<T, LenT> {
Expand All @@ -31,34 +31,14 @@ impl<T, LenT: ValidLength> FixedArray<T, LenT> {
pub fn empty() -> Self {
Self {
ptr: NonNull::dangling(),
len: LenT::DANGLING,
len: LenT::ZERO,
}
}

/// # Safety
/// - `len` must be equal to `ptr.len()`
unsafe fn from_box(ptr: Box<[T]>, len: LenT) -> Self {
let len = LenT::NonZero::new(len).unwrap_or(LenT::DANGLING);

// If the length was 0, the above `unwrap_or` has just set the value to `LenT::DANGLING`.
// If the length was not 0, the invariant is held by the caller.
Self::from_box_with_nonzero(ptr, len)
}

/// # Safety
/// If the slice is empty:
/// - `len` must be equal to `LenT::DANGLING`
///
/// If the slice is not empty:
/// - `len` must be equal to `ptr.len()`
#[must_use]
unsafe fn from_box_with_nonzero(ptr: Box<[T]>, len: LenT::NonZero) -> Self {
#[cfg(debug_assertions)]
if ptr.is_empty() {
assert_eq!(len, LenT::DANGLING);
} else {
assert_eq!(len.into().to_usize(), ptr.len());
}
debug_assert_eq!(len.into().to_usize(), ptr.len());

let array_ptr = Box::into_raw(ptr).cast::<T>();
Self {
Expand All @@ -79,11 +59,7 @@ impl<T, LenT: ValidLength> FixedArray<T, LenT> {
/// Returns the length of the [`FixedArray`].
#[must_use]
pub fn len(&self) -> LenT {
if self.is_empty() {
LenT::ZERO
} else {
self.len.into()
}
self.len
}

/// Returns if the length is equal to 0.
Expand Down Expand Up @@ -165,7 +141,7 @@ impl<T: Clone, LenT: ValidLength> Clone for FixedArray<T, LenT> {
let ptr = self.as_slice().to_vec().into_boxed_slice();

// SAFETY: The Box::from cannot make the length mismatch.
unsafe { Self::from_box_with_nonzero(ptr, self.len) }
unsafe { Self::from_box(ptr, self.len) }
}

#[allow(clippy::assigning_clones)]
Expand Down Expand Up @@ -198,12 +174,6 @@ impl<T: Hash, LenT: ValidLength> Hash for FixedArray<T, LenT> {
}

impl<T: PartialEq, LenT: ValidLength> PartialEq for FixedArray<T, LenT> {
// https://github.com/rust-lang/rust-clippy/issues/12154
#[allow(
unknown_lints,
unconditional_recursion,
clippy::unconditional_recursion
)]
fn eq(&self, other: &Self) -> bool {
self.as_slice().eq(other.as_slice())
}
Expand Down
7 changes: 7 additions & 0 deletions src/length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl TryFrom<InvalidLength<u8>> for InvalidStrLength {
pub trait NonZero<Int: ValidLength>:
sealed::NonZeroSealed + Into<Int> + Sized + Copy + PartialEq + Debug
{
#[expect(unused)]
fn new(val: Int) -> Option<Self>;
}

Expand Down Expand Up @@ -138,8 +139,11 @@ pub trait ValidLength:
{
const ZERO: Self;
const MAX: Self;
#[deprecated = "will be removed in the next major release"]
#[expect(deprecated)]
const DANGLING: Self::NonZero;

#[deprecated = "will be removed in the next major release"]
type NonZero: NonZero<Self>;
#[cfg(feature = "typesize")]
type InlineStrRepr: Copy + AsRef<[u8]> + AsMut<[u8]> + Default + typesize::TypeSize;
Expand All @@ -158,6 +162,7 @@ pub trait ValidLength:
impl ValidLength for u8 {
const ZERO: Self = 0;
const MAX: Self = Self::MAX;
#[expect(deprecated)]
const DANGLING: Self::NonZero = Self::NonZero::MAX;

type NonZero = NonZeroU8;
Expand All @@ -171,6 +176,7 @@ impl ValidLength for u8 {
impl ValidLength for u16 {
const ZERO: Self = 0;
const MAX: Self = Self::MAX;
#[expect(deprecated)]
const DANGLING: Self::NonZero = Self::NonZero::MAX;

type NonZero = NonZeroU16;
Expand All @@ -185,6 +191,7 @@ impl ValidLength for u16 {
impl ValidLength for u32 {
const ZERO: Self = 0;
const MAX: Self = Self::MAX;
#[expect(deprecated)]
const DANGLING: Self::NonZero = Self::NonZero::MAX;

type NonZero = NonZeroU32;
Expand Down

0 comments on commit 3b45676

Please sign in to comment.