macro_rules! assert_has_field {
(@ASSERT $unreachable_obj:ident, $field:ident) => { ... };
(@ASSERT $unreachable_obj:ident, $field:ident : $field_ty:ty) => { ... };
(@ASSERT $unreachable_obj:ident, $field:ident :~ $field_ty:ty) => { ... };
(
$struct:ty,
$field:ident
$($rest:tt)*
) => { ... };
}Expand description
This macro performs a compile-time check if a struct has a specific field.
§Syntax
The macro offers three syntaxes for checking if a struct has a field
assert_has_field!(Struct, field);- checks if the struct has a field with the given name.assert_has_field!(Struct, field: Type);- checks if the struct has a field with the given name and type.assert_has_field!(Struct, field :~ Type);- checks if the struct has a field with the given name and type that can be coerced to the specified typeType.
§Examples
use assert_has_field::assert_has_field;
#[allow(dead_code)]
struct Point {
x: u64,
y: u64,
}
// This will compile because `Point` has a field `x`.
assert_has_field!(Point, x);If the field is not present, the macro will cause a compile-time error.
use assert_has_field::assert_has_field;
#[allow(dead_code)]
struct Point {
x: u64,
y: u64,
}
// This will cause a compile-time error because `Point` does not have a field `a`.
assert_has_field!(Point, a);You can also specify the type of the field to ensure it matches a specific type.
use assert_has_field::assert_has_field;
#[allow(dead_code)]
struct Point {
x: u64,
y: u64,
}
// This will compile because `Point` has a field `x` of type `u64`.
assert_has_field!(Point, x: u64);Note, however, that : syntax in this macro asserts the exact type of the field,
preventing any coercion to minimize the human error.
The following code will not compile:
use assert_has_field::assert_has_field;
struct Wrapper<T>(T);
impl<T> core::ops::Deref for Wrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[allow(dead_code)]
struct Point2 {
x: &'static Wrapper<u64>,
y: u64,
}
// This will cause a compile-time error because `Point2`'s field `x` is of type
// `&'static Wrapper<u64>`, not `&'static u64`.
assert_has_field!(Point2, x: &'static u64);Additionally, you can use the made-up :~ syntax to assert that the field
can be coerced to the specified type.
use assert_has_field::assert_has_field;
#[allow(dead_code)]
struct Wrapper<T>(T);
impl<T> core::ops::Deref for Wrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[allow(dead_code)]
struct Point2 {
x: &'static Wrapper<u64>,
y: u64,
}
// This will compile because `Point2` has a field `x` that can be coerced to `&'static u64`.
assert_has_field!(Point2, x :~ &'static u64);§On real use-cases
Let’s say that you’re writing a backend server and have a DTO, which is meant
to be used on the frontend. Assume that this DTO aggregates different kinds of
data that pertains to a candidate. You may be in a situation where candidate_id
is stored in one of the fields-structures. You can use assert_has_field to
document that expectation and future-proof the type in case the field-structure
that used to store candidate_id is removed entirely or modified in a way that
moves or removes the candidate_id.