xref: /qemu/rust/qemu-api/src/assertions.rs (revision 2e73a17c68f4d80023dc616e596e8c1f3ea8dd75)
1 // Copyright 2024, Red Hat Inc.
2 // Author(s): Paolo Bonzini <pbonzini@redhat.com>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 //! This module provides macros to check the equality of types and
6 //! the type of `struct` fields.  This can be useful to ensure that
7 //! types match the expectations of C code.
8 
9 // Based on https://stackoverflow.com/questions/64251852/x/70978292#70978292
10 // (stackoverflow answers are released under MIT license).
11 
12 #[doc(hidden)]
13 pub trait EqType {
14     type Itself;
15 }
16 
17 impl<T> EqType for T {
18     type Itself = T;
19 }
20 
21 /// Assert that two types are the same.
22 ///
23 /// # Examples
24 ///
25 /// ```
26 /// # use qemu_api::assert_same_type;
27 /// # use std::ops::Deref;
28 /// assert_same_type!(u32, u32);
29 /// assert_same_type!(<Box<u32> as Deref>::Target, u32);
30 /// ```
31 ///
32 /// Different types will cause a compile failure
33 ///
34 /// ```compile_fail
35 /// # use qemu_api::assert_same_type;
36 /// assert_same_type!(&Box<u32>, &u32);
37 /// ```
38 #[macro_export]
39 macro_rules! assert_same_type {
40     ($t1:ty, $t2:ty) => {
41         const _: () = {
42             #[allow(unused)]
43             fn assert_same_type(v: $t1) {
44                 fn types_must_be_equal<T, U>(_: T)
45                 where
46                     T: $crate::assertions::EqType<Itself = U>,
47                 {
48                 }
49                 types_must_be_equal::<_, $t2>(v);
50             }
51         };
52     };
53 }
54 
55 /// Assert that a field of a struct has the given type.
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// # use qemu_api::assert_field_type;
61 /// pub struct A {
62 ///     field1: u32,
63 /// }
64 ///
65 /// assert_field_type!(A, field1, u32);
66 /// ```
67 ///
68 /// Different types will cause a compile failure
69 ///
70 /// ```compile_fail
71 /// # use qemu_api::assert_field_type;
72 /// # pub struct A { field1: u32 }
73 /// assert_field_type!(A, field1, i32);
74 /// ```
75 #[macro_export]
76 macro_rules! assert_field_type {
77     ($t:ty, $i:tt, $ti:ty) => {
78         const _: () = {
79             #[allow(unused)]
80             fn assert_field_type(v: $t) {
81                 fn types_must_be_equal<T, U>(_: T)
82                 where
83                     T: $crate::assertions::EqType<Itself = U>,
84                 {
85                 }
86                 types_must_be_equal::<_, $ti>(v.$i);
87             }
88         };
89     };
90 }
91