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 e62856d
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 0 deletions.
10 changes: 10 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,10 @@
#![allow(unused)]
extern crate zerocopy_derive;
extern crate static_assertions;
use zerocopy_derive::*;
use static_assertions;

#[zerocopy_derive::inline_assert_size_eq(1)]
struct test_size_neq_struct {
i: i8,
}
24 changes: 24 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,24 @@
error[E0254]: the name `static_assertions` is defined multiple times
--> tests/ui-stable/inline_assert_size_eq_failed.rs:5:5
|
3 | extern crate static_assertions;
| ------------------------------- previous import of the extern crate `static_assertions` here
4 | use zerocopy_derive::*;
5 | use static_assertions;
| ^^^^^^^^^^^^^^^^^ `static_assertions` reimported here
|
= note: `static_assertions` must be defined only once in the type namespace of this module

warning: type `test_size_neq_struct` should have an upper camel case name
--> tests/ui-stable/inline_assert_size_eq_failed.rs:8:8
|
8 | struct test_size_neq_struct {
| ^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `TestSizeNeqStruct`
|
= note: `#[warn(non_camel_case_types)]` on by default

error[E0601]: `main` function not found in crate `$CRATE`
--> tests/ui-stable/inline_assert_size_eq_failed.rs:10:2
|
10 | }
| ^ consider adding a `main` function to `$DIR/tests/ui-stable/inline_assert_size_eq_failed.rs`
1 change: 1 addition & 0 deletions tests/ui-stable/inline_assert_size_eq_failed.rs
24 changes: 24 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,24 @@
error[E0254]: the name `static_assertions` is defined multiple times
--> tests/ui-stable/inline_assert_size_eq_failed.rs:5:5
|
3 | extern crate static_assertions;
| ------------------------------- previous import of the extern crate `static_assertions` here
4 | use zerocopy_derive::*;
5 | use static_assertions;
| ^^^^^^^^^^^^^^^^^ `static_assertions` reimported here
|
= note: `static_assertions` must be defined only once in the type namespace of this module

warning: type `test_size_neq_struct` should have an upper camel case name
--> tests/ui-stable/inline_assert_size_eq_failed.rs:8:8
|
8 | struct test_size_neq_struct {
| ^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `TestSizeNeqStruct`
|
= note: `#[warn(non_camel_case_types)]` on by default

error[E0601]: `main` function not found in crate `$CRATE`
--> tests/ui-stable/inline_assert_size_eq_failed.rs:10:2
|
10 | }
| ^ consider adding a `main` function to `$DIR/tests/ui-stable/inline_assert_size_eq_failed.rs`
37 changes: 37 additions & 0 deletions zerocopy-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,43 @@ 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();
if let (Ok(ast), Ok(size)) = (ast, expected_size) {
let name =&ast.ident;
quote! {
#ast
static_assertions::const_assert!(core::mem::size_of::<#name>() == #size);
}.into()
}
else {
input
}

}

// 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 e62856d

Please sign in to comment.