• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // FIXME: Link below is required to render in index
2 /// Asserts that the traits support dynamic dispatch
3 /// ([object-safety](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects)).
4 ///
5 /// This is useful for when changes are made to a trait that accidentally
6 /// prevent it from being used as an [object]. Such a case would be adding a
7 /// generic method and forgetting to add `where Self: Sized` after it. If left
8 /// unnoticed, that mistake will affect crate users and break both forward and
9 /// backward compatibility.
10 ///
11 /// # Examples
12 ///
13 /// When exposing a public API, it's important that traits that could previously
14 /// use dynamic dispatch can still do so in future compatible crate versions.
15 ///
16 /// ```
17 /// # #[macro_use] extern crate static_assertions; fn main() {}
18 /// trait MySafeTrait {
19 ///     fn foo(&self) -> u32;
20 /// }
21 ///
22 /// assert_obj_safe!(std::fmt::Write, MySafeTrait);
23 /// ```
24 ///
25 /// Works with traits that are not in the calling module:
26 ///
27 /// ```
28 /// # #[macro_use] extern crate static_assertions; fn main() {}
29 /// mod inner {
30 ///     pub trait BasicTrait {
31 ///         fn bar(&self);
32 ///     }
33 ///     assert_obj_safe!(BasicTrait);
34 /// }
35 ///
36 /// assert_obj_safe!(inner::BasicTrait);
37 /// ```
38 ///
39 /// The following example fails to compile because raw pointers cannot be sent
40 ///  between threads safely:
41 ///
42 /// ```compile_fail
43 /// # #[macro_use] extern crate static_assertions; fn main() {}
44 /// assert_impl!(*const u8, Send);
45 /// ```
46 ///
47 /// The following example fails to compile because generics without
48 /// `where Self: Sized` are not allowed in [object-safe][object] trait methods:
49 ///
50 /// ```compile_fail
51 /// # #[macro_use] extern crate static_assertions; fn main() {}
52 /// trait MyUnsafeTrait {
53 ///     fn baz<T>(&self) -> T;
54 /// }
55 ///
56 /// assert_obj_safe!(MyUnsafeTrait);
57 /// ```
58 ///
59 /// When we fix that, the previous code will compile:
60 ///
61 /// ```
62 /// # #[macro_use] extern crate static_assertions; fn main() {}
63 /// trait MyUnsafeTrait {
64 ///     fn baz<T>(&self) -> T where Self: Sized;
65 /// }
66 ///
67 /// assert_obj_safe!(MyUnsafeTrait);
68 /// ```
69 ///
70 /// [object]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects
71 #[macro_export]
72 macro_rules! assert_obj_safe {
73     ($($xs:path),+ $(,)?) => {
74         $(const _: Option<&$xs> = None;)+
75     };
76 }
77