1#![allow(clippy::extra_unused_type_parameters)]
2
3use proc_macro2::{
4    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
5};
6
7macro_rules! assert_impl {
8    ($ty:ident is $($marker:ident) and +) => {
9        #[test]
10        #[allow(non_snake_case)]
11        fn $ty() {
12            fn assert_implemented<T: $($marker +)+>() {}
13            assert_implemented::<$ty>();
14        }
15    };
16
17    ($ty:ident is not $($marker:ident) or +) => {
18        #[test]
19        #[allow(non_snake_case)]
20        fn $ty() {
21            $(
22                {
23                    // Implemented for types that implement $marker.
24                    trait IsNotImplemented {
25                        fn assert_not_implemented() {}
26                    }
27                    impl<T: $marker> IsNotImplemented for T {}
28
29                    // Implemented for the type being tested.
30                    trait IsImplemented {
31                        fn assert_not_implemented() {}
32                    }
33                    impl IsImplemented for $ty {}
34
35                    // If $ty does not implement $marker, there is no ambiguity
36                    // in the following trait method call.
37                    <$ty>::assert_not_implemented();
38                }
39            )+
40        }
41    };
42}
43
44assert_impl!(Delimiter is Send and Sync);
45assert_impl!(Spacing is Send and Sync);
46
47assert_impl!(Group is not Send or Sync);
48assert_impl!(Ident is not Send or Sync);
49assert_impl!(LexError is not Send or Sync);
50assert_impl!(Literal is not Send or Sync);
51assert_impl!(Punct is not Send or Sync);
52assert_impl!(Span is not Send or Sync);
53assert_impl!(TokenStream is not Send or Sync);
54assert_impl!(TokenTree is not Send or Sync);
55
56#[cfg(procmacro2_semver_exempt)]
57mod semver_exempt {
58    use proc_macro2::{LineColumn, SourceFile};
59
60    assert_impl!(LineColumn is Send and Sync);
61
62    assert_impl!(SourceFile is not Send or Sync);
63}
64
65mod unwind_safe {
66    use proc_macro2::{
67        Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
68    };
69    #[cfg(procmacro2_semver_exempt)]
70    use proc_macro2::{LineColumn, SourceFile};
71    use std::panic::{RefUnwindSafe, UnwindSafe};
72
73    macro_rules! assert_unwind_safe {
74        ($($types:ident)*) => {
75            $(
76                assert_impl!($types is UnwindSafe and RefUnwindSafe);
77            )*
78        };
79    }
80
81    assert_unwind_safe! {
82        Delimiter
83        Group
84        Ident
85        LexError
86        Literal
87        Punct
88        Spacing
89        Span
90        TokenStream
91        TokenTree
92    }
93
94    #[cfg(procmacro2_semver_exempt)]
95    assert_unwind_safe! {
96        LineColumn
97        SourceFile
98    }
99}
100