Skip to content

ACP ptr::is_aligned_for::<T>() #140979

Duplicate
Duplicate
@mathisbot

Description

@mathisbot
Contributor

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

I would be delighted to open the PR myself if this ACP is accepted and if no one wants to do it first.

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on May 13, 2025
removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on May 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jieyouxu@rustbot@mathisbot

        Issue actions

          ACP `ptr::is_aligned_for::<T>()` · Issue #140979 · rust-lang/rust