assert_type_eq/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//! Statically assert that types from potentially different crate versions via
//! different dependencies are identical.
//!
//! Until RFC 1977 (public dependencies) is accepted, the situation where
//! multiple different versions of the same crate are present is possible. In
//! most situations this will simply cause code to not compile, as types
//! mismatch, however with runtime structures like `TypeMap` this leads to
//! runtime errors (often silent!) instead. This macro allows compile-time
//! assertion that types via different dependencies are identical, and will
//! interoperate, which is easier to debug than runtime errors.
//!
//! Usage:
//!
//! ```
//! #[macro_use]
//! extern crate assert_type_eq;
//!
//! pub mod my_crate {
//!     pub struct MyStruct;
//! }
//!
//! mod a {
//!     pub use super::my_crate;
//! }
//!
//! mod b {
//!     pub use super::my_crate;
//! }
//!
//! assert_type_eq!(
//!     my_crate::MyStruct,
//!     a::my_crate::MyStruct,
//!     b::my_crate::MyStruct,
//! );
//!
//! fn main() {
//!     // ...
//! }
//! ```
//!
//! Specify all versions of the same type via different dependencies. Any types
//! that do not match the first type in the macro will cause a compile-time
//! error.

#[macro_export]
macro_rules! assert_type_eq {
    ( $t:ty, $( $ot:ty ),* $(,)* ) => {
        mod assert_type_eq_mod {
            #[allow(unused_imports)]
            use super::*;

            struct MatchingType<T>(T);

            #[allow(dead_code, unreachable_patterns)]
            fn assert_type_eq(mine: MatchingType<$t>) {
                match mine {
                    $( MatchingType::<$ot>(_) => () ),*
                }
            }
        }
    }
}