Description
ACP: ptr::is_aligned_for::<U>
Summary
This proposal introduces a new method, ptr::is_aligned_for::<U>(self) -> bool
, on raw pointers.
It streamlines alignment checks when casting pointers to a different type by eliminating the need for an intermediate, lint-triggering cast.
The new API mirrors the implementation of ptr::is_aligned
, using the alignment of the target type U.
Motivation
Currently, checking that a pointer is properly aligned for a target type requires a cast prior to invoking ptr.is_aligned()
.
This can trigger the Clippy lint clippy::cast_ptr_alignment
, which users must manually silence even though their check is valid.
Another solution is to call ptr::is_aligned_to
with align_of::<U>()
,
which is still unstable (see #96284) for matters of runtime checks.
This method deals with exactly the same goal as ptr::is_aligned
, i.e. ensuring that the pointer alignment is valid (for aligned reads/writes) after a cast.
As the alignment would be provided by align_of
, the problem of invalid alignments discussed in #96284 are not relevant here.
Motivating examples
type Pixel = u32;
struct Screen {
raw_buffer: &'static mut [Pixel]
}
impl Screen {
pub fn new(raw_buffer: &'static mut [u8], Self) {
let pixel_ptr = {
let buffer_ptr = raw_buffer.as_mut_ptr();
assert!(buffer_ptr.is_aligned_for::<Pixel>(), "Buffer is not aligned for Pixel");
buffer_ptr.cast::<Pixel>()
};
// We can now safely create a slice from the pointer
// as both the alignment and address are valid
let pixel_slice = unsafe {
core::slice::from_raw_parts_mut(
pixel_ptr,
raw_buffer.len() / size_of::<Pixel>()
)
};
}
}
Note: Rewriting Screen::new
with a new signature (i.e. making raw_buffer
a &'static mut [Pixel]
) would only relocate the problem.
The above code can currently only be written as:
let pixel_ptr = {
let buffer_ptr = raw_buffer.as_mut_ptr();
assert!(buffer_ptr.cast::<Pixel>().is_aligned(), "Buffer is not aligned for Pixel");
buffer_ptr.cast::<Pixel>()
};
which I think is less readable.
I am sure that there are examples dealing with FFI that would benefit from this as well (such as when dealing with C-void pointers).
API Design
impl<T: Sized> *const T {
#[must_use]
#[inline]
pub fn is_aligned_for<U: Sized>(self) -> bool;
}
impl<T: Sized> *mut T {
#[must_use]
#[inline]
pub fn is_aligned_for<U: Sized>(self) -> bool;
}
impl<T: Sized> NonNull<T> {
#[must_use]
#[inline]
pub fn is_aligned_for<U: Sized>(self) -> bool;
}
References
ptr::is_aligned
's implementationptr::is_aligned_to
tracking issue
I would be delighted to open the PR myself if this ACP is accepted and if no one wants to do it first.
Activity