Crate static_assertions [−] [src]
Compile-time assertions to ensure that invariants are met.
Usage
This crate is available on crates.io and can be used by adding the
following to your project's Cargo.toml:
[dependencies]
static_assertions = "0.2.3"
and this to your crate root:
#[macro_use] extern crate static_assertions;
Assert Equal Size
When performing operations such as pointer casts or dealing with usize
versus u64 versus u32, the size of your types matter. This is where
assert_eq_size comes into play. Types provided as arguments to
assert_eq_size are ensured to be the same size at compile-time. If the
types differ in size, the code will fail to compile.
// Can be declared outside of a function if labeled assert_eq_size!(bytes; (u8, u8), u16); // Fails to compile (same label): // assert_eq_size!(bytes; u8, u8); fn main() { assert_eq_size!([u8; 4], (u16, u16), u32); // Produces a compilation failure: // assert_eq_size!(u32, u8); }
Similar to assert_eq_size, there is assert_eq_size_val. Instead of
specifying types to compare, values' sizes can be directly compared against
each other.
let x = 42u8; let y = true; assert_eq_size_val!(x, y);
assert_eq_size_val doesn't consume its arguments and thus works for
non-Cloneable values.
struct Buffer([u8; 256]); let buf = Buffer([0; 256]); let val = [0u64; 32]; assert_eq_size_val!(buf, val); // `buf` and `val` can be used here
Rather than dereference a pointer to achieve the same effect as
assert_eq_size_val, there is also the option of assert_eq_size_ptr.
Assert Constant Expression
Constant expressions can be ensured to have certain properties via
const_assert. If the expression evaluates to false, the file will fail
to compile. This is synonymous to static_assert in C++.
As a limitation, a unique label is required if the macro is used outside of a function.
const NUM: usize = 32; const_assert!(NUM * NUM == 1024);
As a shorthand for const_assert!(a == b), there's const_assert_eq:
const TWO: usize = 2; const_assert_eq!(two; TWO * TWO, TWO + TWO, 4); // Fails to compile (same label): // const_assert_eq!(two; TWO, TWO); fn main() { const NUM: usize = 32; const_assert_eq!(NUM + NUM, 64); }
Assert Object Safety
Sometimes changes are made to traits that prevent them from being used in
the context of an object. Such a case would be adding a generic method and
forgetting to add where Self: Sized after it. If left unnoticed, that
mistake will end up affecting crate users and break compatibility.
assert_obj_safe is here to save you from those troubles:
assert_obj_safe!(basic; Send, Sync, AsRef<str>); trait MySafeTrait {} trait MyUnsafeTrait { fn generic<T>(); } fn main() { assert_obj_safe!(MySafeTrait); // Produces a compilation failure: // assert_obj_safe!(MyUnsafeTrait); }
Assert Trait impl
To ensure types implement Send, Sync, and other traits, there's
assert_impl:
assert_impl!(str; String, Send, Sync, From<&'static str>); assert_impl!(vec; &'static [u8], Into<Vec<u8>>); fn main() { // Produces a compilation failure: // `*const u8` cannot be sent between threads safely // assert_impl!(*const u8, Send); }
Limitations
Due to implementation details, the following can only be used normally from within the context of a function:
To use these macros in other contexts, a unique label must be provided.
If you want to read up about this and provide feedback, see the related issue on GitHub.
Macros
| assert_eq_size |
Asserts at compile-time that the types have equal sizes. |
| assert_eq_size_ptr |
Asserts at compile-time that the values pointed to have equal sizes. |
| assert_eq_size_val |
Asserts at compile-time that the values have equal sizes. |
| assert_impl |
Asserts at compile-time that the type implements the given traits. |
| assert_obj_safe |
Asserts at compile-time that the traits are object-safe. |
| const_assert |
Asserts at compile-time that the constant expression evaluates to |
| const_assert_eq |
Asserts at compile-time that the constants are equal in value. |