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-Clone
able 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. |