Check reference alignment in `const fn`?

I have the following function:

fn aligned_to(bytes: &[u8], align: usize) -> bool {
    (bytes as *const _ as *const () as usize) % align == 0
}

I'd like to make it a const fn, but if I just do that without changing the implementation, the compiler complains:

error: pointers cannot be cast to integers during const eval
    --> src/lib.rs:1636:5
     |
1636 |     (bytes as *const _ as *const () as usize) % align == 0
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = note: at compile-time, pointers do not have an integer value
     = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior

Is there a different way to implement the same API that only uses const-safe operations? I can't figure out a way.

You definitely won't be able to do it using arithmetic, since addresses don't exist at const-evaluation time, but there are operations specifically for alignment available. Unfortunately, none of them are stably const.

The one which is exactly what you want is pointer::is_aligned_to but that's not stable and not const. pointer::align_offset is unstably const, but apparently that's because it's allowed to fail and always fails in const eval.

I imagine that if you want to achieve this you'll have to make a proposal for the compiler to support it, with a use case to justify it. Right now, I would expect that a const &[u8] simply does not have an alignment — its address is abstract and, if it persists through to run time, it could in principle be placed in memory with any alignment.

4 Likes

OK thanks @kpreid! Disappointing, but very insightful!