[Pre-RFC] Add a new offset_of macro to core::mem

@mjbshaw ah, const fn is a very tough additional constraint. Your code looks a lot like what memoffset had! It also used to support const fn. And transmuting 0 into a reference causes SIGILL on some platforms. :confused:

Could you try to use mem::align_of::<$parent>() instead of 0? That would be slightly less UB. :wink: In fact that would make it basically equivalent to the pre-MaybeUninit version that is currently in memoffset.

And you could also force evaluation to happen at CTFE, thereby avoiding run-time trouble:

macro_rules! offset_of {
    ($parent:tt, $field:tt) => {{
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        let $parent { $field: _, .. };
        // FORCING code to be const-eval'ed so that it can
        // not cause run-time trouble.
        const OFFSET: usize = {
            union TransmuteHack<T: Copy, U: Copy> {
                from: T,
                to: U,
            }
            unsafe {
                TransmuteHack::<_, usize> {
                    from: &TransmuteHack::<usize, &'static $parent> {
                        // Properly aligned to maintain at least *some*
                        // properties of a valid reference.
                        from: std::mem::align_of::<$parent>(),
                    }.to.$field,
                }.to - std::mem::align_of::<$parent>()
            }
        };
        OFFSET
    }}
}

I also added Deref-coercion-protection.

Here's a small test of this on the playground.

3 Likes