Skip to content

Commit

Permalink
add align_of! for computing alignment of DSTs
Browse files Browse the repository at this point in the history
The `align_of!` macro uses `trailing_field_offset!` to compute the
alignment of DSTs with minimum alignments up to 65536. By contrast,
`core::mem::align_of` does not support DSTs.

Makes progress on #29.
  • Loading branch information
jswrenn committed Oct 31, 2023
1 parent 89ca5ab commit 49c18f6
Showing 1 changed file with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions src/macro_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,26 @@ macro_rules! trailing_field_offset {
}};
}

/// Computes alignment of `$ty`.
///
/// `align_of!` produces code which is valid in a `const` context.
// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
// `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
#[macro_export]
macro_rules! align_of {
($t:ty) => {{
#[repr(C)]
struct OffsetOfTrailingIsAlignment {
_byte: u8,
_trailing: $t,
}

trailing_field_offset!(OffsetOfTrailingIsAlignment, _trailing)
}};
}

/// Does the struct type `$t` have padding?
///
/// `$ts` is the list of the type of every field in `$t`. `$t` must be a
Expand Down Expand Up @@ -524,6 +544,47 @@ mod tests {
*/
}

// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove
// this `cfg` when `size_of_val_raw` is stabilized.
#[allow(clippy::decimal_literal_representation)]
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[test]
fn test_align_of_dst() {
// Test that `align_of!` correctly computes the alignment of DSTs.
assert_eq!(align_of!([elain::Align<1>]), Some(1));
assert_eq!(align_of!([elain::Align<2>]), Some(2));
assert_eq!(align_of!([elain::Align<4>]), Some(4));
assert_eq!(align_of!([elain::Align<8>]), Some(8));
assert_eq!(align_of!([elain::Align<16>]), Some(16));
assert_eq!(align_of!([elain::Align<32>]), Some(32));
assert_eq!(align_of!([elain::Align<64>]), Some(64));
assert_eq!(align_of!([elain::Align<128>]), Some(128));
assert_eq!(align_of!([elain::Align<256>]), Some(256));
assert_eq!(align_of!([elain::Align<512>]), Some(512));
assert_eq!(align_of!([elain::Align<1024>]), Some(1024));
assert_eq!(align_of!([elain::Align<2048>]), Some(2048));
assert_eq!(align_of!([elain::Align<4096>]), Some(4096));
assert_eq!(align_of!([elain::Align<8192>]), Some(8192));
assert_eq!(align_of!([elain::Align<16384>]), Some(16384));
assert_eq!(align_of!([elain::Align<32768>]), Some(32768));
assert_eq!(align_of!([elain::Align<65536>]), Some(65536));
/* Alignments above 65536 are not yet supported.
assert_eq!(align_of!([elain::Align<131072>]), Some(131072));
assert_eq!(align_of!([elain::Align<262144>]), Some(262144));
assert_eq!(align_of!([elain::Align<524288>]), Some(524288));
assert_eq!(align_of!([elain::Align<1048576>]), Some(1048576));
assert_eq!(align_of!([elain::Align<2097152>]), Some(2097152));
assert_eq!(align_of!([elain::Align<4194304>]), Some(4194304));
assert_eq!(align_of!([elain::Align<8388608>]), Some(8388608));
assert_eq!(align_of!([elain::Align<16777216>]), Some(16777216));
assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432));
assert_eq!(align_of!([elain::Align<67108864>]), Some(67108864));
assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432));
assert_eq!(align_of!([elain::Align<134217728>]), Some(134217728));
assert_eq!(align_of!([elain::Align<268435456>]), Some(268435456));
*/
}

#[test]
fn test_struct_has_padding() {
// Test that, for each provided repr, `struct_has_padding!` reports the
Expand Down

0 comments on commit 49c18f6

Please sign in to comment.