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
The only unresolved question raised since then is whatever panicking in is_aligned_to on non-power of two align is acceptable.
API Summary
impl*constT{pubfnis_aligned(self) -> boolwhereT:Sized;pubfnis_aligned_to(self,align:usize) -> bool;}// ... and the same for` *mut T`
Experience Report
#100820 and #100823 refactored some std code into using these methods simplifying the code.
These methods were long requested (see for example #56304) and seem to be quite nice to use. They also may have slightly better codegen, compared to naive % align implementation.
I think the unresolved question needs an answer, not just a mention.
As I brought up earlier, I think it'd be really nice to have a type for valid alignments. The other two options are both unfortunate, IMHO: needing to assert!(align.is_power_of_two()) in something that would otherwise be a trivial bit of code, or just going 🤷 and returning garbage if the input isn't a power of two.
So, our options for resolving the unresolved question:
Leave as-is, assert!(align.is_power_of_two())
Pros: notifies users of about invalid usages
Cons: in some cases adds an additional check/panic
Make behavior is case of !align.is_power_of_two() implementation defined (non-sensible result, debug_assert!, etc)
Pros: no performance penalty, ever
Cons: does not notify users about invalid usages
Introduce a type that holds always valid alignment
Pros: impossible to use incorrectly, such type can improve other APIs as well
Cons: bigger API surface, users need to move to new APIs (align_of2::<T>() -> Align?...), given an usize (e.g. from an external library) you need a trailing_zeros call to convert back
@tyler274 they can't, CTFE engine (compile time function execution) does not (necessarily) have a notion of "address" of a pointer. Since you can't take the address (e.g. it's UB to transmute::<*const (), usize>() in CTFE) you also can't check if it's divisible by something.
given an usize (e.g. from an external library) you need a trailing_zeros call to convert back
That's assuming it would be stored as log_2(align), but that's not necessary. In fact, the type that Layout uses internally today stores it as the power of two -- since that's convenient for things like the usual &(align-1) trick. So using a usize from an external library would be a "free" Alignment::new_unchecked call (if you can trust that other library).
Question from the libs-api meeting: How often would one use is_aligned_to given that is_aligned exists? (Or maybe a is_aligned_for::<T>() might suffice for most cases?)
How often does one want to check a calculated alignment rather than a constant alignment? With e.g. .is_aligned_to(16), the check would be optimized away, making the usize argument fine. Using a separate Alignment type would only add extra verbosity.
Status update: I originally planned to use grep.app or an alternative to gather stats about "is aligned" checks in the wild. But... I did not have enough courage to finish the work and now I simply do not have the capacity for that.
If anyone wants to take this from here (and answer t-libs-api questions in the above post) — feel free to.
Just want to point out a valid use case this function provides that none of the alternatives offer: type erasure. With all the provided alternatives, you have to specify a type in order to check alignment, which means that you're required to instantiate a surrounding method specifically for that type when checking alignment. In this case, you can have a type-erased version and just pass a usize for the alignment to the method.
Considering how often code that deals with pointers try to reduce code bloat, even avoiding methods like Option::map as a result, it makes sense that is_aligned_to will still be preferred over alternatives like try_cast_aligned which still require a type.
Also worth pointing out that this is currently doable by checking ptr.align_offset(align) == 0, so, this is strictly just a readability improvement.
In fact, for many use cases where the alignment comes from a non-erased type, the newer API #141221 is better than checking the alignment and then casting the pointee type in separate steps.
When type erasure is used, the alignment will generally be a runtime value. In those cases, eliding the power of two check via an Alignment newtype (as discussed above) is especially useful, since the compiler can’t just inline some code to and see that the usize argument is a power of two. Conversely, if we’re going to have the Alignment type at all (cc #102070), then “test if an address is aligned” seems like a fairly natural and basic operation for it, along with “round size to multiple of alignment” and an align_offset equivalent.
Would people be in favour of changing this to use the Alignment type? That would address the unresolved question.
I don't see how that guarantees removing the pow of 2 check? Alignment::new() still needs to check that usize is a power of 2, short of using the new unchecked method. Also for some things it's a little more clunky to first have to create new instance of Alignment and then do you comparison. I think having both are fine. If I would add anything to this it would probably be this:
// an other name could be is_aligned_to_log2()/// Is the ptr aligned to 2^powpubfnis_aligned_to_pow(self,pow:u32) -> bool{debug_assert!(pow <= usize::BITS);let mask = usize::MAX >> (usize::BITS - pow);(self.addr()& mask) == 0}
There are various ways to construct Alignment that avoid the pow2 check by construction, e.g., Alignment::of::<T>(), Alignment::of_val(x), and layout.alignment(). The latter two can involve values that aren’t compile time constants (loaded from dyn Trait vtable or from a runtime Layout value) which would in general need a runtime pow2 check when using usize (align_of_val(x) and layout.align()).
It’s debatable if the cases where this saves a runtime check outweigh the cases where you just want to use an usize constant. I don’t have a very clear picture of the use cases. But I’ll point out that in the compile time constant cases, the alignment will probably be used for more than just the alignment check, so any boilerplate of Alignment construction can be folded into const FOO_ALIGN: Alignment = …; which may be desirable anyway.
It’s debatable if the cases where this saves a runtime check outweigh the cases where you just want to use an usize constant. I don’t have a very clear picture of the use cases. But I’ll point out that in the compile time constant cases, the alignment will probably be used for more than just the alignment check, so any boilerplate of Alignment construction can be folded into const FOO_ALIGN: Alignment = …; which may be desirable anyway.
I'll say that if the current API if the alignment is a constant the pow2 check is often elided: https://godbolt.org/z/1h6n1fhYz
A case where you don't have type information or a const would be something like an allocator. At least with nightly the Allocator API it gets a Layout, and at least as part Alignment API, you can get an Alignment from a Layout, but other things that are similar/ allocator like may not have a Layout or Alignment just a usize. For example allocating things for an FFI obviously your are not going to get an Alignment, just a usize or some int/uint.
They also hardware/device constraints or configuration. Like you might have to query a register or some memory mapped configuration depending on the mode/configuration the hardware is operating in to get a required alignment. You can't necessarily get those constraints like those at compile time unless they are fixed to always be the same for device.
There also protocols where certain things are basically negotiated, so things are setup at runtime so again can't be known at compile time.
They are probably other cases I am not thinking of that's just what came to mind.
Although this is just a small nice convenience function I suppose anywhere where that check could hurt performance more than desired it is super easy to write a function that skips the check your self.
Activity
scottmcm commentedon Aug 21, 2022
For the unresolved question: another option might be to expose https://stdrs.dev/nightly/x86_64-unknown-linux-gnu/core/mem/valid_align/struct.ValidAlign.html and use it as the parameter type.
WaffleLapkin commentedon Sep 4, 2022
I want to propose to stabilize these methods! (can someone open an fcp?)
Stabilization report
Implementation History
pointer::is_aligned_to#100169is_aligned_toon non-power of two align is acceptable.API Summary
Experience Report
#100820 and #100823 refactored some std code into using these methods simplifying the code.
These methods were long requested (see for example #56304) and seem to be quite nice to use. They also may have slightly better codegen, compared to naive
% alignimplementation.scottmcm commentedon Sep 6, 2022
I think the unresolved question needs an answer, not just a mention.
As I brought up earlier, I think it'd be really nice to have a type for valid alignments. The other two options are both unfortunate, IMHO: needing to
assert!(align.is_power_of_two())in something that would otherwise be a trivial bit of code, or just going 🤷 and returning garbage if the input isn't a power of two.WaffleLapkin commentedon Sep 11, 2022
So, our options for resolving the unresolved question:
assert!(align.is_power_of_two())!align.is_power_of_two()implementation defined (non-sensible result,debug_assert!, etc)align_of2::<T>() -> Align?...), given anusize(e.g. from an external library) you need atrailing_zeroscall to convert backI'm leaning towards 2, but that's just me 🤷
tyler274 commentedon Sep 14, 2022
Could these methods be made
const fns ?WaffleLapkin commentedon Sep 14, 2022
@tyler274 they can't, CTFE engine (compile time function execution) does not (necessarily) have a notion of "address" of a pointer. Since you can't take the address (e.g. it's UB to
transmute::<*const (), usize>()in CTFE) you also can't check if it's divisible by something.scottmcm commentedon Sep 16, 2022
That's assuming it would be stored as
log_2(align), but that's not necessary. In fact, the type thatLayoutuses internally today stores it as the power of two -- since that's convenient for things like the usual&(align-1)trick. So using ausizefrom an external library would be a "free"Alignment::new_uncheckedcall (if you can trust that other library).EDIT: I opened an ACP to add an
Alignmentnewtype to core: rust-lang/libs-team#108m-ou-se commentedon Sep 20, 2022
Question from the libs-api meeting: How often would one use
is_aligned_togiven thatis_alignedexists? (Or maybe ais_aligned_for::<T>()might suffice for most cases?)How often does one want to check a calculated alignment rather than a constant alignment? With e.g.
.is_aligned_to(16), the check would be optimized away, making theusizeargument fine. Using a separateAlignmenttype would only add extra verbosity.WaffleLapkin commentedon Sep 18, 2023
Status update: I originally planned to use grep.app or an alternative to gather stats about "is aligned" checks in the wild. But... I did not have enough courage to finish the work and now I simply do not have the capacity for that.
If anyone wants to take this from here (and answer t-libs-api questions in the above post) — feel free to.
2 remaining items
downgrade ptr.is_aligned_to crate-private
downgrade ptr.is_aligned_to crate-private
downgrade ptr.is_aligned_to crate-private
downgrade ptr.is_aligned_to crate-private
downgrade ptr.is_aligned_to crate-private
Gankra commentedon Mar 3, 2024
I propose we split the feature into two and stabilize the perfectly inoffensive
ptr.is_aligned(), which handles 95% of usecases.[-]Tracking Issue for pointer_is_aligned[/-][+]Tracking Issue for pointer_is_aligned_to[/+]clarfonthey commentedon Jan 24, 2026
Just want to point out a valid use case this function provides that none of the alternatives offer: type erasure. With all the provided alternatives, you have to specify a type in order to check alignment, which means that you're required to instantiate a surrounding method specifically for that type when checking alignment. In this case, you can have a type-erased version and just pass a
usizefor the alignment to the method.Considering how often code that deals with pointers try to reduce code bloat, even avoiding methods like
Option::mapas a result, it makes sense thatis_aligned_towill still be preferred over alternatives liketry_cast_alignedwhich still require a type.Also worth pointing out that this is currently doable by checking
ptr.align_offset(align) == 0, so, this is strictly just a readability improvement.hanna-kruppe commentedon Jan 24, 2026
In fact, for many use cases where the alignment comes from a non-erased type, the newer API #141221 is better than checking the alignment and then casting the pointee type in separate steps.
When type erasure is used, the alignment will generally be a runtime value. In those cases, eliding the power of two check via an
Alignmentnewtype (as discussed above) is especially useful, since the compiler can’t just inline some code to and see that theusizeargument is a power of two. Conversely, if we’re going to have theAlignmenttype at all (cc #102070), then “test if an address is aligned” seems like a fairly natural and basic operation for it, along with “round size to multiple of alignment” and analign_offsetequivalent.ChrisDenton commentedon Jan 24, 2026
Would people be in favour of changing this to use the
Alignmenttype? That would address the unresolved question.Keith-Cancel commentedon May 13, 2026
I don't see how that guarantees removing the pow of 2 check?
Alignment::new()still needs to check that usize is a power of 2, short of using the new unchecked method. Also for some things it's a little more clunky to first have to create new instance ofAlignmentand then do you comparison. I think having both are fine. If I would add anything to this it would probably be this:hanna-kruppe commentedon May 13, 2026
There are various ways to construct
Alignmentthat avoid the pow2 check by construction, e.g.,Alignment::of::<T>(),Alignment::of_val(x), andlayout.alignment(). The latter two can involve values that aren’t compile time constants (loaded fromdyn Traitvtable or from a runtimeLayoutvalue) which would in general need a runtime pow2 check when usingusize(align_of_val(x)andlayout.align()).It’s debatable if the cases where this saves a runtime check outweigh the cases where you just want to use an usize constant. I don’t have a very clear picture of the use cases. But I’ll point out that in the compile time constant cases, the alignment will probably be used for more than just the alignment check, so any boilerplate of
Alignmentconstruction can be folded intoconst FOO_ALIGN: Alignment = …;which may be desirable anyway.Keith-Cancel commentedon May 14, 2026
I'll say that if the current API if the alignment is a constant the pow2 check is often elided: https://godbolt.org/z/1h6n1fhYz
A case where you don't have type information or a const would be something like an allocator. At least with nightly the
AllocatorAPI it gets aLayout, and at least as partAlignmentAPI, you can get anAlignmentfrom aLayout, but other things that are similar/ allocator like may not have aLayoutorAlignmentjust a usize. For example allocating things for an FFI obviously your are not going to get anAlignment, just ausizeor some int/uint.They also hardware/device constraints or configuration. Like you might have to query a register or some memory mapped configuration depending on the mode/configuration the hardware is operating in to get a required alignment. You can't necessarily get those constraints like those at compile time unless they are fixed to always be the same for device.
There also protocols where certain things are basically negotiated, so things are setup at runtime so again can't be known at compile time.
They are probably other cases I am not thinking of that's just what came to mind.
Although this is just a small nice convenience function I suppose anywhere where that check could hurt performance more than desired it is super easy to write a function that skips the check your self.