diff --git a/src/lib.rs b/src/lib.rs index 6291545..86d7051 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ ptr_offset_from, const_ptr_offset_from, const_transmute, - const_raw_ptr_deref + const_raw_ptr_deref, ) )] #![cfg_attr(feature = "unstable_raw", feature(raw_ref_macros))] diff --git a/src/offset_of.rs b/src/offset_of.rs index 72b15c5..9a50fd7 100644 --- a/src/offset_of.rs +++ b/src/offset_of.rs @@ -31,7 +31,9 @@ macro_rules! _memoffset__let_base_ptr { // `let_base_ptr` declares a variable (several, actually) // instead of returning one. let uninit = $crate::mem::MaybeUninit::<$type>::uninit(); - let $name = uninit.as_ptr(); + // Transmuting for const-compatibility. + #[allow(unused_unsafe)] // for when the macro is used in an unsafe block + let $name: *const $type = unsafe { $crate::mem::transmute(&uninit) }; }; } #[cfg(not(maybe_uninit))] @@ -72,7 +74,7 @@ macro_rules! offset_of { _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field!(base_ptr, $parent, $field); - // Compute offset. + // Compute offset, as integers to make the fewest assumptions. (field_ptr as usize) - (base_ptr as usize) }}; } @@ -82,19 +84,12 @@ macro_rules! offset_of { macro_rules! offset_of { ($parent:path, $field:tt) => {{ // Get a base pointer. - // No UB here, and the pointer does not dangle, either. - let uninit = $crate::mem::MaybeUninit::<$parent>::uninit(); - #[allow(unused_unsafe)] // for when the macro is used in an unsafe block - unsafe { - // This, on the other hand, *is* UB, since we're creating a reference - // to uninitialized data. - // Unfortunately it's the best we can do at the moment. - let base_ptr = $crate::mem::transmute::<_, &$parent>(&uninit) as *const $parent; - // Get a field pointer. - let field_ptr = raw_field!(base_ptr, $parent, $field); - // Compute offset. - (field_ptr as *const u8).offset_from(base_ptr as *const u8) as usize - } + _memoffset__let_base_ptr!(base_ptr, $parent); + // Get field pointer. + let field_ptr = raw_field!(base_ptr, $parent, $field); + // Compute offset, with unstable `offset_from` for const-compatibility. + // (Requires the pointers to not dangle, but we already need that for `raw_field!` anyway.) + unsafe { (field_ptr as *const u8).offset_from(base_ptr as *const u8) as usize } }}; } diff --git a/src/raw_field.rs b/src/raw_field.rs index ee4a631..ec7255c 100644 --- a/src/raw_field.rs +++ b/src/raw_field.rs @@ -31,28 +31,6 @@ macro_rules! _memoffset__field_check { }; } -/// Computes a const raw pointer to the given field of the given base pointer -/// to the given parent type. -/// -/// The `base` pointer *must not* be dangling, but it *may* point to -/// uninitialized memory. -#[cfg(feature = "unstable_raw")] // Correct variant that uses `raw_const!`. -#[macro_export(local_inner_macros)] -macro_rules! raw_field { - ($base:expr, $parent:path, $field:tt) => {{ - _memoffset__field_check!($parent, $field); - let base_ptr: *const $parent = $base; - - // Get the field address without creating a reference. - // Crucially, we know that this will not trigger a deref coercion because - // of the `field_check!` we did above. - #[allow(unused_unsafe)] // for when the macro is used in an unsafe block - unsafe { - $crate::ptr::raw_const!((*base_ptr).$field) - } - }}; -} - /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent type. /// @@ -76,3 +54,20 @@ macro_rules! raw_field { } }}; } + +#[cfg(feature = "unstable_raw")] // Correct variant that uses `raw_const!`. +#[macro_export(local_inner_macros)] +macro_rules! raw_field { + ($base:expr, $parent:path, $field:tt) => {{ + _memoffset__field_check!($parent, $field); + let base_ptr: *const $parent = $base; + + // Get the field address without creating a reference. + // Crucially, we know that this will not trigger a deref coercion because + // of the `field_check!` we did above. + #[allow(unused_unsafe)] // for when the macro is used in an unsafe block + unsafe { + $crate::ptr::raw_const!((*base_ptr).$field) + } + }}; +}