Advertisement
Guest User

Untitled

a guest
Oct 21st, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.38 KB | None | 0 0
  1. #[macro_export]
  2. macro_rules! assert_impl_any {
  3. ($x:ty: $($t:path),+ $(,)?) => {
  4. const _: fn() = || {
  5. use core::marker::PhantomData;
  6. use core::ops::Deref;
  7.  
  8. struct AssertAnyTraitNoTrait;
  9. let next = AssertAnyTraitNoTrait;
  10.  
  11. // Ensures that blanket traits can't impersonate the method.
  12. struct AssertAnyTraitToken;
  13. $(
  14. let next = {
  15. struct Wrapper<T, N>(PhantomData<T>, N);
  16. impl<T, N> Deref for Wrapper<T, N> {
  17. type Target = N;
  18. fn deref(&self) -> &Self::Target {
  19. &self.1
  20. }
  21. }
  22. impl<T: $t, N> Wrapper<T, N> {
  23. #[allow(non_snake_case)]
  24. // The `TOKEN` generic ensures that a method on a blanket trait can't be generic and therefore accept the `AssertAnyTraitToken`.
  25. fn __static_assert__has_any_trait<TOKEN>(&self, _: AssertAnyTraitToken) {}
  26. }
  27. Wrapper::<$x, _>(PhantomData, next)
  28. };
  29. )+
  30. next.__static_assert__has_any_trait::<()>(AssertAnyTraitToken);
  31. };
  32. };
  33. }
  34.  
  35. mod tests {
  36. #[test]
  37. fn should_compile() {
  38. assert_impl_any!((): Send, Sync);
  39. assert_impl_any!((): Send, From<u8>);
  40. }
  41.  
  42. /// The macro isn't perfect and a trait with the correct method name can interfere with the macro.
  43. ///
  44. /// This tests the case with interference where the macro should normally fail. The interference still causes the macro to fail so this doesn't really matter.
  45. ///
  46. /// ```compile_fail
  47. /// use playground::assert_impl_any;
  48. ///
  49. /// trait Interfere {
  50. /// #[allow(non_snake_case)]
  51. /// fn __static_assert__has_any_trait<A>(&self, token: A) {}
  52. /// }
  53. /// impl<T> Interfere for T {}
  54. ///
  55. /// // This test would fail if this is true: These should fail to compile but the above trait interferes and causes them to actually compile anyway.
  56. /// assert_impl_any!((): From<u8>);
  57. /// assert_impl_any!((): From<u8>, From<u16>);
  58. /// ```
  59. #[allow(dead_code)]
  60. fn interference_for_fail_case() {}
  61.  
  62. /// The macro isn't perfect and a trait with the correct method name can interfere with the macro.
  63. ///
  64. /// This tests the case with interference where the macro should normally succeed. The interference causes the macro to fail, this isn't really a problem since it is very unlikely that the correct trait actually exists.
  65. ///
  66. /// ```compile_fail
  67. /// use playground::assert_impl_any;
  68. ///
  69. /// trait Interfere {
  70. /// #[allow(non_snake_case)]
  71. /// fn __static_assert__has_any_trait(&self: token: ()) {}
  72. /// }
  73. /// impl<T> Interfere for T {}
  74. ///
  75. /// // These should actually compile but the above trait interferes and causes them to fail anyway.
  76. /// assert_impl_any!((): Send, Sync);
  77. /// assert_impl_any!((): Send, From<u8>);
  78. /// ```
  79. #[allow(dead_code)]
  80. fn interference_for_success_case() {}
  81.  
  82. /// A function that should fail to compile.
  83. ///
  84. /// ```compile_fail
  85. /// use playground::assert_impl_any;
  86. /// assert_impl_any!((): From<u8>);
  87. /// assert_impl_any!((): From<u8>, From<u16>);
  88. /// ```
  89. #[allow(dead_code)]
  90. fn should_fail() {}
  91. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement