1 #![allow(clippy::let_underscore_untyped)]
2 
3 use paste::paste;
4 
5 #[test]
test_shared_hygiene()6 fn test_shared_hygiene() {
7     paste! {
8         let [<a a>] = 1;
9         assert_eq!([<a a>], 1);
10     }
11 }
12 
13 #[test]
test_repeat()14 fn test_repeat() {
15     const ROCKET_A: &str = "/a";
16     const ROCKET_B: &str = "/b";
17 
18     macro_rules! routes {
19         ($($route:ident),*) => {{
20             paste! {
21                 vec![$( [<ROCKET_ $route>] ),*]
22             }
23         }}
24     }
25 
26     let routes = routes!(A, B);
27     assert_eq!(routes, vec!["/a", "/b"]);
28 }
29 
30 #[test]
test_literal_to_identifier()31 fn test_literal_to_identifier() {
32     const CONST0: &str = "const0";
33 
34     let pasted = paste!([<CONST 0>]);
35     assert_eq!(pasted, CONST0);
36 
37     let pasted = paste!([<CONST '0'>]);
38     assert_eq!(pasted, CONST0);
39 
40     let pasted = paste!([<CONST "0">]);
41     assert_eq!(pasted, CONST0);
42 
43     let pasted = paste!([<CONST r"0">]);
44     assert_eq!(pasted, CONST0);
45 
46     let pasted = paste!([<CONST '\u{30}'>]);
47     assert_eq!(pasted, CONST0);
48 }
49 
50 #[test]
test_literal_suffix()51 fn test_literal_suffix() {
52     macro_rules! literal {
53         ($bit:tt) => {
54             paste!([<1_u $bit>])
55         };
56     }
57 
58     assert_eq!(literal!(32), 1);
59 }
60 
61 #[test]
test_underscore()62 fn test_underscore() {
63     paste! {
64         const A_B: usize = 0;
65         assert_eq!([<A _ B>], 0);
66     }
67 }
68 
69 #[test]
test_lifetime()70 fn test_lifetime() {
71     paste! {
72         #[allow(dead_code)]
73         struct S<[<'d e>]> {
74             q: &[<'d e>] str,
75         }
76     }
77 }
78 
79 #[test]
test_keyword()80 fn test_keyword() {
81     paste! {
82         struct [<F move>];
83 
84         let _ = Fmove;
85     }
86 }
87 
88 #[test]
test_literal_str()89 fn test_literal_str() {
90     paste! {
91         #[allow(non_camel_case_types)]
92         struct [<Foo "Bar-Baz">];
93 
94         let _ = FooBar_Baz;
95     }
96 }
97 
98 #[test]
test_env_literal()99 fn test_env_literal() {
100     paste! {
101         struct [<Lib env bar>];
102 
103         let _ = Libenvbar;
104     }
105 }
106 
107 #[test]
test_env_present()108 fn test_env_present() {
109     paste! {
110         struct [<Lib env!("CARGO_PKG_NAME")>];
111 
112         let _ = Libpaste;
113     }
114 }
115 
116 #[test]
test_raw_identifier()117 fn test_raw_identifier() {
118     paste! {
119         struct [<F r#move>];
120 
121         let _ = Fmove;
122     }
123 }
124 
125 #[test]
test_false_start()126 fn test_false_start() {
127     trait Trait {
128         fn f() -> usize;
129     }
130 
131     struct S;
132 
133     impl Trait for S {
134         fn f() -> usize {
135             0
136         }
137     }
138 
139     paste! {
140         let x = [<S as Trait>::f()];
141         assert_eq!(x[0], 0);
142     }
143 }
144 
145 #[test]
test_local_variable()146 fn test_local_variable() {
147     let yy = 0;
148 
149     paste! {
150         assert_eq!([<y y>], 0);
151     }
152 }
153 
154 #[test]
test_empty()155 fn test_empty() {
156     paste! {
157         assert_eq!(stringify!([<y y>]), "yy");
158         assert_eq!(stringify!([<>]).replace(' ', ""), "[<>]");
159     }
160 }
161 
162 #[test]
test_env_to_lower()163 fn test_env_to_lower() {
164     paste! {
165         struct [<Lib env!("CARGO_PKG_NAME"):lower>];
166 
167         let _ = Libpaste;
168     }
169 }
170 
171 #[test]
test_env_to_upper()172 fn test_env_to_upper() {
173     paste! {
174         const [<LIB env!("CARGO_PKG_NAME"):upper>]: &str = "libpaste";
175 
176         let _ = LIBPASTE;
177     }
178 }
179 
180 #[test]
test_env_to_snake()181 fn test_env_to_snake() {
182     paste! {
183         const [<LIB env!("CARGO_PKG_NAME"):snake:upper>]: &str = "libpaste";
184 
185         let _ = LIBPASTE;
186     }
187 }
188 
189 #[test]
test_env_to_camel()190 fn test_env_to_camel() {
191     paste! {
192         #[allow(non_upper_case_globals)]
193         const [<LIB env!("CARGO_PKG_NAME"):camel>]: &str = "libpaste";
194 
195         let _ = LIBPaste;
196     }
197 }
198 
199 mod test_x86_feature_literal {
200     // work around https://github.com/rust-lang/rust/issues/72726
201 
202     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
203     macro_rules! my_is_x86_feature_detected {
204         ($feat:literal) => {
205             use paste::paste;
206 
207             paste! {
208                 #[test]
209                 fn test() {
210                     let _ = is_x86_feature_detected!($feat);
211                 }
212             }
213         };
214     }
215 
216     #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
217     macro_rules! my_is_x86_feature_detected {
218         ($feat:literal) => {
219             #[ignore]
220             #[test]
221             fn test() {}
222         };
223     }
224 
225     my_is_x86_feature_detected!("mmx");
226 }
227 
228 #[rustversion::since(1.46)]
229 mod test_local_setter {
230     // https://github.com/dtolnay/paste/issues/7
231 
232     use paste::paste;
233 
234     #[derive(Default)]
235     struct Test {
236         val: i32,
237     }
238 
239     impl Test {
set_val(&mut self, arg: i32)240         fn set_val(&mut self, arg: i32) {
241             self.val = arg;
242         }
243     }
244 
245     macro_rules! setter {
246         ($obj:expr, $field:ident, $value:expr) => {
247             paste! { $obj.[<set_ $field>]($value); }
248         };
249 
250         ($field:ident, $value:expr) => {{
251             let mut new = Test::default();
252             setter!(new, val, $value);
253             new
254         }};
255     }
256 
257     #[test]
test_local_setter()258     fn test_local_setter() {
259         let a = setter!(val, 42);
260         assert_eq!(a.val, 42);
261     }
262 }
263 
264 // https://github.com/dtolnay/paste/issues/85
265 #[test]
test_top_level_none_delimiter()266 fn test_top_level_none_delimiter() {
267     macro_rules! clone {
268         ($val:expr) => {
269             paste! {
270                 $val.clone()
271             }
272         };
273     }
274 
275     #[derive(Clone)]
276     struct A;
277 
278     impl A {
279         fn consume_self(self) {
280             let _ = self;
281         }
282     }
283 
284     clone!(&A).consume_self();
285 }
286