Skip to content

Commit

Permalink
Implement Inline Size Assertion Annotations
Browse files Browse the repository at this point in the history
Implem the procedural macro `inline_assert_size_eq` to check the size of
a type at compile time. Additionally, add the test file
`inline_assert_size_eq_failed.rs` to ensure that the macro tirggers a
compile-time error when the size is not as expected
Fixes google#1329
  • Loading branch information
zoo868e committed Jun 9, 2024
1 parent f1f0184 commit aa9d014
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 0 deletions.
9 changes: 9 additions & 0 deletions tests/ui-nightly/inline_assert_size_eq_failed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
extern crate zerocopy_derive;
use zerocopy_derive::inline_assert_size_eq;

#[inline_assert_size_eq(1)]
struct TestSizeNeqStruct {
i: i32,
}

fn main() {}
7 changes: 7 additions & 0 deletions tests/ui-nightly/inline_assert_size_eq_failed.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error[E0080]: evaluation of constant value failed
--> tests/ui-nightly/inline_assert_size_eq_failed.rs:4:1
|
4 | #[inline_assert_size_eq(1)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
|
= note: this error originates in the macro `static_assertions::const_assert` which comes from the expansion of the attribute macro `inline_assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
1 change: 1 addition & 0 deletions tests/ui-stable/inline_assert_size_eq_failed.rs
7 changes: 7 additions & 0 deletions tests/ui-stable/inline_assert_size_eq_failed.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error[E0080]: evaluation of constant value failed
--> tests/ui-stable/inline_assert_size_eq_failed.rs:4:1
|
4 | #[inline_assert_size_eq(1)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
|
= note: this error originates in the macro `static_assertions::const_assert` which comes from the expansion of the attribute macro `inline_assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
39 changes: 39 additions & 0 deletions zerocopy-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,45 @@ macro_rules! try_or_print {
};
}

/// Inline size assertion annotations
/// Any non-generic type can be check if the size is as expected or not in compile time
/// # Implementation
/// ```
/// # use zerocopy_derive::inline_assert_size_eq;
/// # use static_assertions;
/// #[inline_assert_size_eq(4)]
/// struct MyStruct {
/// val: i32
/// }
/// ```
/// # Example that will fail
/// ```compile_fail
/// # use zero_derive::inline_assert_size_eq;
/// # use static_assertions;
/// #[inline_assert_size_eq(1)]
/// struct MyStruct {
/// val: i32
/// }
/// ```
#[proc_macro_attribute]
pub fn inline_assert_size_eq(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let ast: Result<DeriveInput, _> = syn::parse(input.clone());
let expected_size: Result<usize, _> = args.to_string().trim().parse();
let mut ret: proc_macro::TokenStream = input;
if let (Ok(ast), Ok(size)) = (ast, expected_size) {
let name = &ast.ident;
ret = quote! {
#ast
static_assertions::const_assert!(core::mem::size_of::<#name>() == #size);
}
.into()
}
ret
}

// TODO(https://github.com/rust-lang/rust/issues/54140): Some errors could be
// made better if we could add multiple lines of error output like this:
//
Expand Down

0 comments on commit aa9d014

Please sign in to comment.