You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 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 both less expressive and 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) 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
typePixel = u32;structScreen{raw_buffer:&'staticmut[Pixel]}implScreen{pubfnnew(raw_buffer:&'staticmut[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 validlet pixel_slice = unsafe{
core::slice::from_raw_parts_mut(
pixel_ptr,
raw_buffer.len() / size_of::<Pixel>())};Self{raw_buffer: pixel_slice }}}
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).
This ensures the pointer is cast to the exact same type as the one used for alignment checks.
Rare cases (such as FFI) where only the boolean value is needed could use ptr.try_cast_aligned::<SomeType>().is_some().
The implementation would be a combination of is_aligned_to and cast, so it would compile down to exactly the same assembly as the hypothetical is_aligned_for.
The only downside of this solution is that it loses the verbosity of is_aligned_for in such cases.
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.
The lint would have to learn to not warn about casts guarded by a is_aligned_for check. Probably doable, but as an outsider to clippy it’s not clear to me that this will be much easier than recognizing the cast + is_aligned pattern.
This ties to my other reservation about the proposal as written: while it allows checking alignment before casting, it doesn’t help with ensuring check + cast are always done together and agree on the type. An alternative would be something closer to <[T]>::align_to that combines alignment check and cast: try_cast_aligned(Ptr<T>) -> Option<Ptr<U>>.
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
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
withalign_of::<U>()
,which is both less expressive and 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) 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
The above code can currently only be written as:
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
Alternative solutions
As stated and suggested by @hanna-kruppe, it would be wise to group alignment check and cast as follows:
This ensures the pointer is cast to the exact same type as the one used for alignment checks.
Rare cases (such as FFI) where only the boolean value is needed could use
ptr.try_cast_aligned::<SomeType>().is_some()
.The implementation would be a combination of
is_aligned_to
andcast
, so it would compile down to exactly the same assembly as the hypotheticalis_aligned_for
.The only downside of this solution is that it loses the verbosity of
is_aligned_for
in such cases.References
ptr::is_aligned
's implementationptr::is_aligned_to
tracking issueTracking issue: Tracking Issue for
pointer_is_aligned_for
rust#140980PR: Implement
ptr::is_aligned_for
andNonNull::is_aligned_for
. rust#140982The text was updated successfully, but these errors were encountered: