]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir_ty/src/tests/macros.rs
812f171db8ed428ccf7a996294cd000b66f7d73e
[rust.git] / crates / ra_hir_ty / src / tests / macros.rs
1 use super::{infer, type_at, type_at_pos};
2 use crate::test_db::TestDB;
3 use insta::assert_snapshot;
4 use ra_db::fixture::WithFixture;
5
6 #[test]
7 fn cfg_impl_block() {
8     let (db, pos) = TestDB::with_position(
9         r#"
10 //- /main.rs crate:main deps:foo cfg:test
11 use foo::S as T;
12 struct S;
13
14 #[cfg(test)]
15 impl S {
16     fn foo1(&self) -> i32 { 0 }
17 }
18
19 #[cfg(not(test))]
20 impl S {
21     fn foo2(&self) -> i32 { 0 }
22 }
23
24 fn test() {
25     let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
26     t<|>;
27 }
28
29 //- /foo.rs crate:foo
30 struct S;
31
32 #[cfg(not(test))]
33 impl S {
34     fn foo3(&self) -> i32 { 0 }
35 }
36
37 #[cfg(test)]
38 impl S {
39     fn foo4(&self) -> i32 { 0 }
40 }
41 "#,
42     );
43     assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
44 }
45
46 #[test]
47 fn infer_macros_expanded() {
48     assert_snapshot!(
49         infer(r#"
50 struct Foo(Vec<i32>);
51
52 macro_rules! foo {
53     ($($item:expr),*) => {
54             {
55                 Foo(vec![$($item,)*])
56             }
57     };
58 }
59
60 fn main() {
61     let x = foo!(1,2);
62 }
63 "#),
64         @r###"
65     ![0; 17) '{Foo(v...,2,])}': Foo
66     ![1; 4) 'Foo': Foo({unknown}) -> Foo
67     ![1; 16) 'Foo(vec![1,2,])': Foo
68     ![5; 15) 'vec![1,2,]': {unknown}
69     [156; 182) '{     ...,2); }': ()
70     [166; 167) 'x': Foo
71     "###
72     );
73 }
74
75 #[test]
76 fn infer_legacy_textual_scoped_macros_expanded() {
77     assert_snapshot!(
78         infer(r#"
79 struct Foo(Vec<i32>);
80
81 #[macro_use]
82 mod m {
83     macro_rules! foo {
84         ($($item:expr),*) => {
85             {
86                 Foo(vec![$($item,)*])
87             }
88         };
89     }
90 }
91
92 fn main() {
93     let x = foo!(1,2);
94     let y = crate::foo!(1,2);
95 }
96 "#),
97         @r###"
98     ![0; 17) '{Foo(v...,2,])}': Foo
99     ![1; 4) 'Foo': Foo({unknown}) -> Foo
100     ![1; 16) 'Foo(vec![1,2,])': Foo
101     ![5; 15) 'vec![1,2,]': {unknown}
102     [195; 251) '{     ...,2); }': ()
103     [205; 206) 'x': Foo
104     [228; 229) 'y': {unknown}
105     [232; 248) 'crate:...!(1,2)': {unknown}
106     "###
107     );
108 }
109
110 #[test]
111 fn infer_path_qualified_macros_expanded() {
112     assert_snapshot!(
113         infer(r#"
114 #[macro_export]
115 macro_rules! foo {
116     () => { 42i32 }
117 }
118
119 mod m {
120     pub use super::foo as bar;
121 }
122
123 fn main() {
124     let x = crate::foo!();
125     let y = m::bar!();
126 }
127 "#),
128         @r###"
129     ![0; 5) '42i32': i32
130     ![0; 5) '42i32': i32
131     [111; 164) '{     ...!(); }': ()
132     [121; 122) 'x': i32
133     [148; 149) 'y': i32
134     "###
135     );
136 }
137
138 #[test]
139 fn infer_type_value_macro_having_same_name() {
140     assert_snapshot!(
141         infer(r#"
142 #[macro_export]
143 macro_rules! foo {
144     () => {
145         mod foo {
146             pub use super::foo;
147         }
148     };
149     ($x:tt) => {
150         $x
151     };
152 }
153
154 foo!();
155
156 fn foo() {
157     let foo = foo::foo!(42i32);
158 }
159 "#),
160         @r###"
161     ![0; 5) '42i32': i32
162     [171; 206) '{     ...32); }': ()
163     [181; 184) 'foo': i32
164     "###
165     );
166 }
167
168 #[test]
169 fn processes_impls_generated_by_macros() {
170     let t = type_at(
171         r#"
172 //- /main.rs
173 macro_rules! m {
174     ($ident:ident) => (impl Trait for $ident {})
175 }
176 trait Trait { fn foo(self) -> u128 {} }
177 struct S;
178 m!(S);
179 fn test() { S.foo()<|>; }
180 "#,
181     );
182     assert_eq!(t, "u128");
183 }
184
185 #[test]
186 fn infer_macro_with_dollar_crate_is_correct_in_expr() {
187     let (db, pos) = TestDB::with_position(
188         r#"
189 //- /main.rs crate:main deps:foo
190 fn test() {
191     let x = (foo::foo!(1), foo::foo!(2));
192     x<|>;
193 }
194
195 //- /lib.rs crate:foo
196 #[macro_export]
197 macro_rules! foo {
198     (1) => { $crate::bar!() };
199     (2) => { 1 + $crate::baz() };
200 }
201
202 #[macro_export]
203 macro_rules! bar {
204     () => { 42 }
205 }
206
207 pub fn baz() -> usize { 31usize }
208 "#,
209     );
210     assert_eq!("(i32, usize)", type_at_pos(&db, pos));
211 }
212
213 #[test]
214 fn infer_type_value_non_legacy_macro_use_as() {
215     assert_snapshot!(
216         infer(r#"
217 mod m {
218     macro_rules! _foo {
219         ($x:ident) => { type $x = u64; }
220     }
221     pub(crate) use _foo as foo;
222 }
223
224 m::foo!(foo);
225 use foo as bar;
226 fn f() -> bar { 0 }
227 fn main() {  
228     let _a  = f();
229 }
230 "#),
231         @r###"
232         [159; 164) '{ 0 }': u64
233         [161; 162) '0': u64
234         [175; 199) '{     ...f(); }': ()
235         [187; 189) '_a': u64
236         [193; 194) 'f': fn f() -> u64
237         [193; 196) 'f()': u64        
238     "###
239     );
240 }
241
242 #[test]
243 fn infer_builtin_macros_line() {
244     assert_snapshot!(
245         infer(r#"
246 #[rustc_builtin_macro]
247 macro_rules! line {() => {}}
248
249 fn main() {
250     let x = line!();
251 }
252 "#),
253         @r###"
254     ![0; 1) '6': i32
255     [64; 88) '{     ...!(); }': ()
256     [74; 75) 'x': i32
257     "###
258     );
259 }
260
261 #[test]
262 fn infer_builtin_macros_file() {
263     assert_snapshot!(
264         infer(r#"
265 #[rustc_builtin_macro]
266 macro_rules! file {() => {}}
267
268 fn main() {
269     let x = file!();
270 }
271 "#),
272         @r###"
273     ![0; 2) '""': &str
274     [64; 88) '{     ...!(); }': ()
275     [74; 75) 'x': &str
276     "###
277     );
278 }
279
280 #[test]
281 fn infer_builtin_macros_column() {
282     assert_snapshot!(
283         infer(r#"
284 #[rustc_builtin_macro]
285 macro_rules! column {() => {}}
286
287 fn main() {
288     let x = column!();
289 }
290 "#),
291         @r###"
292     ![0; 2) '13': i32
293     [66; 92) '{     ...!(); }': ()
294     [76; 77) 'x': i32
295     "###
296     );
297 }
298
299 #[test]
300 fn infer_derive_clone_simple() {
301     let (db, pos) = TestDB::with_position(
302         r#"
303 //- /main.rs crate:main deps:std
304 #[derive(Clone)]
305 struct S;
306 fn test() {
307     S.clone()<|>;
308 }
309
310 //- /lib.rs crate:std
311 #[prelude_import]
312 use clone::*;
313 mod clone {
314     trait Clone {
315         fn clone(&self) -> Self;
316     }
317 }
318 "#,
319     );
320     assert_eq!("S", type_at_pos(&db, pos));
321 }
322
323 #[test]
324 fn infer_derive_clone_with_params() {
325     let (db, pos) = TestDB::with_position(
326         r#"
327 //- /main.rs crate:main deps:std
328 #[derive(Clone)]
329 struct S;
330 #[derive(Clone)]
331 struct Wrapper<T>(T);
332 struct NonClone;
333 fn test() {
334     (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>;
335 }
336
337 //- /lib.rs crate:std
338 #[prelude_import]
339 use clone::*;
340 mod clone {
341     trait Clone {
342         fn clone(&self) -> Self;
343     }
344 }
345 "#,
346     );
347     assert_eq!("(Wrapper<S>, {unknown})", type_at_pos(&db, pos));
348 }