Skip to content

Tracking Issue for pointer_is_aligned_to #96284

Open

Description

@Gankra

Feature gate: #![feature(pointer_is_aligned)]
Feature gate: #![feature(pointer_is_aligned_to)]

This is a tracking issue for ptr.is_aligned() and ptr.is_aligned_to(alignment).

Public API

impl *const T {
    // feature gate `pointer_is_aligned` was stabilized
    // pub fn is_aligned(self) -> bool where T: Sized;
    // feature gate `pointer_is_aligned_to`
    pub fn is_aligned_to(self, align: usize) -> bool;
}
// ... and the same for` *mut T`

impl <T: ?Sized> NonNull<T> {
    pub const fn is_aligned_to(self, align: usize) -> bool;
}

Steps / History

pointer_is_aligned:

pointer_is_aligned_to:

Unresolved Questions

  • Should is_aligned_to require a power of two or should it be more flexible? (currently panics)

Activity

  1. added
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Apr 21, 2022
  2. scottmcm commented on Aug 21, 2022

    @scottmcm
    Member

    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.

  3. WaffleLapkin commented on Sep 4, 2022

    @WaffleLapkin
    Member

    I want to propose to stabilize these methods! (can someone open an fcp?)

    Stabilization report

    Implementation History

    API Summary

    impl *const T {
        pub fn is_aligned(self) -> bool where T: Sized;
        pub fn is_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.

  4. scottmcm commented on Sep 6, 2022

    @scottmcm
    Member

    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.

  5. WaffleLapkin commented on Sep 11, 2022

    @WaffleLapkin
    Member

    So, our options for resolving the unresolved question:

    1. 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
    2. 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
    3. 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

    I'm leaning towards 2, but that's just me 🤷

  6. tyler274 commented on Sep 14, 2022

    @tyler274

    Could these methods be made const fns ?

  7. WaffleLapkin commented on Sep 14, 2022

    @WaffleLapkin
    Member

    @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.

  8. scottmcm commented on Sep 16, 2022

    @scottmcm
    Member

    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).

    EDIT: I opened an ACP to add an Alignment newtype to core: rust-lang/libs-team#108

  9. m-ou-se commented on Sep 20, 2022

    @m-ou-se
    Member

    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.

  10. WaffleLapkin commented on Sep 18, 2023

    @WaffleLapkin
    Member

    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.

  11. 2 remaining items

  12. Gankra commented on Mar 3, 2024

    @Gankra
    ContributorAuthor

    I propose we split the feature into two and stabilize the perfectly inoffensive ptr.is_aligned(), which handles 95% of usecases.

  13. changed the title [-]Tracking Issue for pointer_is_aligned[/-] [+]Tracking Issue for pointer_is_aligned_to[/+] on Mar 30, 2024
  14. clarfonthey commented on Jan 24, 2026

    @clarfonthey
    Contributor

    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.

  15. hanna-kruppe commented on Jan 24, 2026

    @hanna-kruppe
    Contributor

    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.

  16. ChrisDenton commented on Jan 24, 2026

    @ChrisDenton
    Member

    Would people be in favour of changing this to use the Alignment type? That would address the unresolved question.

  17. Keith-Cancel commented on May 13, 2026

    @Keith-Cancel
    Contributor

    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^pow
    pub fn is_aligned_to_pow(self, pow: u32) -> bool {
        debug_assert!(pow <= usize::BITS);
        let mask = usize::MAX >> (usize::BITS - pow);
        (self.addr() & mask) == 0
    }
  18. hanna-kruppe commented on May 13, 2026

    @hanna-kruppe
    Contributor

    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.

  19. Keith-Cancel commented on May 14, 2026

    @Keith-Cancel
    Contributor

    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.

  20. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
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

    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions