Skip to content

Commit 63c8f71

Browse files
committed
inline and improve type_props.rs
1 parent ab57893 commit 63c8f71

File tree

9 files changed

+212
-102
lines changed

9 files changed

+212
-102
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ _no versions before 0.13.2 have a changelog as I started the changelog in that v
66

77
- [Version 0.16.0 Predicted](#version-0160-predicted)
88
- [Version 0.15.0](#version-0150)
9+
- [Commit 4](#commit-4-2025-8-05)
10+
- [Commit 3](#commit-3-2025-8-05)
11+
- [Commit 2](#commit-2-2025-8-05)
912
- [Commit 1](#commit-1-2025-8-05)
1013
- [Version 0.14.3](#version-0143-2025-8-05)
1114
- [Commit 2](#commit-2-2025-8-04)
@@ -35,6 +38,11 @@ _no versions before 0.13.2 have a changelog as I started the changelog in that v
3538

3639
## Version 0.15.0
3740

41+
### Commit 4 (2025-8-05)
42+
43+
- Inline error.rs, external_alloc/mod.rs, and type_props.rs
44+
- Generally improve type_props
45+
3846
### Commit 3 (2025-8-05)
3947

4048
- Inline unstable.rs

src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub enum AllocError {
3131

3232
// manual implementations because of the `OtherErr` variant, which can't be PEq, Eq, or Hash
3333
impl PartialEq for AllocError {
34+
#[inline]
3435
fn eq(&self, other: &AllocError) -> bool {
3536
use AllocError::{
3637
AllocFailed, GrowSmallerNewLayout, InvalidLayout, Other, ShrinkBiggerNewLayout,

src/external_alloc/mod.rs

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,17 @@ pub mod ffi {
8888
}
8989
}
9090

91-
/// Returns the usable size of the allocation pointed to by ptr.
92-
///
93-
/// The return value may be larger than the size requested during allocation. This function
94-
/// is not a mechanism for in-place `realloc()`; rather, it is provided solely as a tool for
95-
/// introspection purposes. Any discrepancy between the requested allocation size and the
96-
/// size reported by this function should not be depended on, since such behavior is
97-
/// entirely implementation-dependent.
98-
///
99-
/// # Safety
100-
///
101-
/// `ptr` must have been allocated by jemalloc and must not have been freed yet.
102-
#[must_use]
103-
pub unsafe fn usable_size<T>(ptr: *const T) -> usize {
104-
malloc_usable_size(ptr.cast::<c_void>()) as usize
105-
}
91+
// /// Returns the usable size of the allocation pointed to by ptr.
92+
// ///
93+
// /// The return value may be larger than the size requested during allocation. This function
94+
// /// is not a mechanism for in-place `realloc()`; rather, it is provided solely as a tool for
95+
// /// introspection purposes. Any discrepancy between the requested allocation size and the
96+
// /// size reported by this function should not be depended on, since such behavior is
97+
// /// entirely implementation-dependent.
98+
// ///
99+
// /// # Safety
100+
// ///
101+
// /// `ptr` must have been allocated by jemalloc and must not have been freed yet.
106102

107103
#[cfg_attr(miri, track_caller)]
108104
pub(crate) unsafe fn raw_ralloc(
@@ -124,17 +120,11 @@ pub mod ffi {
124120
#[cfg(feature = "mimalloc")]
125121
/// Bindings from `mimalloc-sys`.
126122
pub mod mim {
127-
use libc::c_void;
128-
129-
/// Returns the usable size of the allocation pointed to by ptr.
130-
///
131-
/// # Safety
132-
///
133-
/// `ptr` must have been allocated by mimalloc and must not have been freed yet.
134-
#[must_use]
135-
pub unsafe fn usable_size<T>(ptr: *const T) -> usize {
136-
mi_usable_size(ptr.cast::<c_void>())
137-
}
123+
// /// Returns the usable size of the allocation pointed to by ptr.
124+
// ///
125+
// /// # Safety
126+
// ///
127+
// /// `ptr` must have been allocated by mimalloc and must not have been freed yet.
138128

139129
pub use memapi_mimalloc_sys::*;
140130
}

src/features/alloc_ext.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub trait AllocExt: Alloc {
9090
data,
9191
|p, data| unsafe {
9292
let guard =
93-
AllocGuard::new(NonNull::<T>::from_raw_parts(p, ptr::metadata(data)), self);
93+
AllocGuard::new(NonNull::<T>::from_raw_parts(p, data.metadata()), self);
9494
data.clone_to_uninit(guard.as_ptr() as *mut u8);
9595
guard.release()
9696
},
@@ -295,7 +295,7 @@ pub trait AllocExt: Alloc {
295295
) -> Result<NonNull<T>, AllocError> {
296296
alloc_then(self, unsafe { data.layout() }, data, |p, data| {
297297
ptr::copy_nonoverlapping(data.cast::<u8>(), p.as_ptr(), data.size());
298-
NonNull::from_raw_parts(p, core::ptr::metadata(data))
298+
NonNull::from_raw_parts(p, data.metadata())
299299
})
300300
}
301301

src/helpers.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
use crate::{
2+
type_props::{
3+
varsized_nonnull_from_raw_parts,
4+
varsized_pointer_from_raw_parts,
5+
VarSized,
6+
PtrProps,
7+
SizedProps,
8+
USIZE_MAX_NO_HIGH_BIT
9+
},
210
error::AllocError,
3-
type_props::{PtrProps, SizedProps, USIZE_MAX_NO_HIGH_BIT},
4-
Alloc,
11+
Alloc
512
};
613
use core::{
714
alloc::Layout,
@@ -31,19 +38,19 @@ pub(crate) fn alloc_then<Ret, A: Alloc + ?Sized, E, F: Fn(NonNull<u8>, E) -> Ret
3138
/// after this crate's MSRV.
3239
#[must_use]
3340
pub const fn nonnull_slice_from_raw_parts<T>(p: NonNull<T>, len: usize) -> NonNull<[T]> {
34-
unsafe { NonNull::new_unchecked(slice_ptr_from_raw_parts(p.as_ptr(), len)) }
41+
varsized_nonnull_from_raw_parts(p.cast(), len)
3542
}
3643

3744
/// Creates a `*mut [T]` from a pointer and a length.
3845
///
3946
/// This is a helper used in place of [`ptr::slice_from_raw_parts_mut`], which was
4047
/// const-stabilized after this crate's MSRV.
4148
///
42-
#[doc = "## Small disclaimer: you must guarantee this function will work, as Rust's fat \
49+
#[doc = "## Small disclaimer: the caller must guarantee this function will work, as Rust's fat \
4350
pointers changing layout would result in this function causing UB."]
4451
#[must_use]
4552
pub const fn slice_ptr_from_raw_parts<T>(p: *mut T, len: usize) -> *mut [T] {
46-
unsafe { transmute::<(*mut T, usize), *mut [T]>((p, len)) }
53+
varsized_pointer_from_raw_parts(p.cast(), len)
4754
}
4855

4956
const_if! {
@@ -130,12 +137,12 @@ pub const unsafe fn dangling_nonnull(align: usize) -> NonNull<u8> {
130137

131138
// here only because it may be used elsewhere later
132139
#[cfg(feature = "alloc_slice")]
133-
/// Gets either a valid layout with space for `n` count of `T`, or an
140+
/// Gets either a valid layout with space for `n` count of `T`, or an
134141
/// `AllocError::LayoutError(sz, aln)`.
135142
pub(crate) const fn layout_or_err<T>(n: usize) -> Result<Layout, AllocError> {
136143
match layout_or_sz_align::<T>(n) {
137144
Ok(l) => Ok(l),
138-
Err((sz, aln)) => Err(AllocError::InvalidLayout(sz, aln))
145+
Err((sz, aln)) => Err(AllocError::InvalidLayout(sz, aln)),
139146
}
140147
}
141148

src/type_props.rs

Lines changed: 123 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ use core::{
55
mem::{align_of, align_of_val, size_of, size_of_val},
66
ptr::NonNull,
77
};
8+
use crate::helpers::dangling_nonnull;
89

910
/// The maximum value of a `usize` with no high bit.
11+
///
12+
/// Equivalent to `usize::MAX >> 1` or `isize::MAX as usize`.
1013
pub const USIZE_MAX_NO_HIGH_BIT: usize = usize::MAX >> 1;
1114

1215
/// A trait containing constants for sized types.
@@ -37,7 +40,7 @@ pub trait PtrProps<T: ?Sized> {
3740
/// # Safety
3841
///
3942
/// The pointer must be valid as a reference.
40-
unsafe fn size(&self) -> usize;
43+
unsafe fn size(&self) -> usize;
4144
/// Gets the alignment of the value.
4245
///
4346
/// # Safety
@@ -49,7 +52,10 @@ pub trait PtrProps<T: ?Sized> {
4952
/// # Safety
5053
///
5154
/// The pointer must be valid as a reference.
52-
unsafe fn layout(&self) -> Layout;
55+
#[inline]
56+
unsafe fn layout(&self) -> Layout {
57+
Layout::from_size_align_unchecked(self.size(), self.align())
58+
}
5359

5460
#[cfg(feature = "metadata")]
5561
/// Gets the metadata of the value.
@@ -82,51 +88,91 @@ pub trait PtrProps<T: ?Sized> {
8288
}
8389
}
8490

85-
/// Implements [`PtrProps`] for a pointer type.
86-
macro_rules! impl_ptr_props {
87-
($($name:ty $(,$to_ptr:ident)?)*) => {
88-
$(
89-
impl<T: ?Sized> PtrProps<T> for $name {
90-
unsafe fn size(&self) -> usize {
91-
// We use &*(*val) (?.to_ptr()?) to convert any primitive pointer type to a
92-
// reference.
93-
// This is kind of a hack, but it lets us avoid *_of_val_raw, which is unstable.
94-
size_of_val::<T>(&*(*self)$(.$to_ptr())?)
95-
}
96-
97-
unsafe fn align(&self) -> usize {
98-
align_of_val::<T>(&*(*self)$(.$to_ptr())?)
99-
}
100-
101-
unsafe fn layout(&self) -> Layout {
102-
Layout::from_size_align_unchecked(
103-
self.size(),
104-
self.align()
105-
)
106-
}
107-
108-
#[cfg(feature = "metadata")]
109-
unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
110-
core::ptr::metadata(&*(*self)$(.$to_ptr())?)
111-
}
112-
}
113-
)*
114-
}
91+
macro_rules! impl_ptr_props_raw {
92+
($($name:ty),* $(,)?) => {
93+
$(
94+
impl<T: ?Sized> PtrProps<T> for $name {
95+
#[inline]
96+
unsafe fn size(&self) -> usize {
97+
size_of_val::<T>(&**self)
98+
}
99+
#[inline]
100+
unsafe fn align(&self) -> usize {
101+
align_of_val::<T>(&**self)
102+
}
103+
#[cfg(feature = "metadata")]
104+
unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
105+
core::ptr::metadata(&*(*self))
106+
}
107+
}
108+
)*
109+
};
115110
}
116111

117-
impl_ptr_props!(
118-
*const T
119-
*mut T
120-
121-
&T
122-
&mut T
112+
macro_rules! impl_ptr_props_identity {
113+
($($name:ty),* $(,)?) => {
114+
$(
115+
impl<T: ?Sized> PtrProps<T> for $name {
116+
#[inline]
117+
unsafe fn size(&self) -> usize {
118+
size_of_val::<T>(*self)
119+
}
120+
#[inline]
121+
unsafe fn align(&self) -> usize {
122+
align_of_val::<T>(*self)
123+
}
124+
#[cfg(feature = "metadata")]
125+
unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
126+
core::ptr::metadata(*self)
127+
}
128+
}
129+
)*
130+
};
131+
}
123132

124-
NonNull<T>, as_ptr
133+
macro_rules! impl_ptr_props_as_ref {
134+
($($name:ty),* $(,)?) => {
135+
$(
136+
impl<T: ?Sized> PtrProps<T> for $name {
137+
#[inline]
138+
unsafe fn size(&self) -> usize {
139+
size_of_val::<T>(self.as_ref())
140+
}
141+
#[inline]
142+
unsafe fn align(&self) -> usize {
143+
align_of_val::<T>(self.as_ref())
144+
}
145+
#[cfg(feature = "metadata")]
146+
unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
147+
core::ptr::metadata(self.as_ref())
148+
}
149+
}
150+
)*
151+
};
152+
}
125153

126-
alloc::boxed::Box<T>
127-
alloc::rc::Rc<T>
154+
impl_ptr_props_raw! { *const T, *mut T }
155+
impl_ptr_props_identity! { &T, &mut T }
156+
impl_ptr_props_as_ref! {
157+
alloc::boxed::Box<T>,
158+
alloc::rc::Rc<T>,
128159
alloc::sync::Arc<T>
129-
);
160+
}
161+
162+
impl<T: ?Sized> PtrProps<T> for NonNull<T> {
163+
#[inline]
164+
unsafe fn size(&self) -> usize {
165+
size_of_val::<T>(&*self.as_ptr())
166+
}
167+
#[inline]
168+
unsafe fn align(&self) -> usize {
169+
align_of_val::<T>(&*self.as_ptr())
170+
}
171+
#[cfg(feature = "metadata")]
172+
unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
173+
core::ptr::metadata(&*self.as_ptr())
174+
}
175+
}
130176

131177
#[cfg(not(feature = "metadata"))]
132178
/// Trait for unsized types whose metadata is `usize` (e.g., slices, `str`).
@@ -152,6 +198,10 @@ pub unsafe trait VarSized: core::ptr::Pointee<Metadata = usize> {
152198
const ALIGN: usize;
153199
}
154200

201+
unsafe impl<T> VarSized for [T] {
202+
const ALIGN: usize = T::ALIGN;
203+
}
204+
155205
unsafe impl VarSized for str {
156206
const ALIGN: usize = u8::ALIGN;
157207
}
@@ -161,7 +211,7 @@ unsafe impl VarSized for core::ffi::CStr {
161211
const ALIGN: usize = u8::ALIGN;
162212
}
163213
#[cfg(feature = "std")]
164-
// `OsStr == [u8]` and `[u8]: UnsizedCopy`
214+
// `OsStr == [u8]` and `[u8]: VarSized`
165215
unsafe impl VarSized for std::ffi::OsStr {
166216
const ALIGN: usize = u8::ALIGN;
167217
}
@@ -171,16 +221,39 @@ unsafe impl VarSized for std::path::Path {
171221
const ALIGN: usize = u8::ALIGN;
172222
}
173223

174-
unsafe impl<T> VarSized for [T] {
175-
const ALIGN: usize = T::ALIGN;
176-
}
177-
178224
// not associated to reduce clutter, and so they can be const
179225

180-
#[cfg(feature = "metadata")]
181226
/// Creates a dangling, zero-length, [`NonNull`] pointer with the proper alignment.
182227
#[must_use]
183228
pub const fn varsized_dangling_nonnull<T: ?Sized + VarSized>() -> NonNull<T> {
184-
// SAFETY: `ALIGN` is guaranteed to be a valid alignment for `Self`.
185-
unsafe { NonNull::from_raw_parts(crate::helpers::dangling_nonnull(T::ALIGN), 0) }
229+
varsized_nonnull_from_raw_parts(unsafe { dangling_nonnull(T::ALIGN) }, 0)
230+
}
231+
232+
#[must_use]
233+
pub const fn varsized_dangling_pointer<T: ?Sized + VarSized>() -> *mut T {
234+
varsized_pointer_from_raw_parts(unsafe { dangling_nonnull(T::ALIGN).as_ptr() }, 0)
235+
}
236+
237+
/// Creates a `NonNull<T>` from a pointer and a `usize` size metadata.
238+
#[must_use]
239+
#[inline]
240+
pub const fn varsized_nonnull_from_raw_parts<T: ?Sized + VarSized>(
241+
p: NonNull<u8>,
242+
meta: usize,
243+
) -> NonNull<T> {
244+
unsafe { NonNull::new_unchecked(varsized_pointer_from_raw_parts(p.as_ptr(), meta)) }
245+
}
246+
247+
/// Creates a `*mut T` from a pointer and a `usize` size metadata.
248+
#[must_use]
249+
#[inline]
250+
pub const fn varsized_pointer_from_raw_parts<T: ?Sized + VarSized>(
251+
p: *mut u8,
252+
meta: usize,
253+
) -> *mut T {
254+
// SAFETY: VarSized trait requires T::Metadata == usize
255+
unsafe {
256+
// i hate this so much
257+
*((&(p, meta)) as *const (*mut u8, usize)).cast::<*mut T>()
258+
}
186259
}

0 commit comments

Comments
 (0)