]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/macros.rs
Merge #5733
[rust.git] / crates / hir_ty / src / tests / macros.rs
1 use std::fs;
2
3 use expect_test::expect;
4 use test_utils::project_dir;
5
6 use super::{check_infer, check_types};
7
8 #[test]
9 fn cfg_impl_def() {
10     check_types(
11         r#"
12 //- /main.rs crate:main deps:foo cfg:test
13 use foo::S as T;
14 struct S;
15
16 #[cfg(test)]
17 impl S {
18     fn foo1(&self) -> i32 { 0 }
19 }
20
21 #[cfg(not(test))]
22 impl S {
23     fn foo2(&self) -> i32 { 0 }
24 }
25
26 fn test() {
27     let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
28     t;
29 } //^ (i32, {unknown}, i32, {unknown})
30
31 //- /foo.rs crate:foo
32 struct S;
33
34 #[cfg(not(test))]
35 impl S {
36     fn foo3(&self) -> i32 { 0 }
37 }
38
39 #[cfg(test)]
40 impl S {
41     fn foo4(&self) -> i32 { 0 }
42 }
43 "#,
44     );
45 }
46
47 #[test]
48 fn infer_macros_expanded() {
49     check_infer(
50         r#"
51         struct Foo(Vec<i32>);
52
53         macro_rules! foo {
54             ($($item:expr),*) => {
55                     {
56                         Foo(vec![$($item,)*])
57                     }
58             };
59         }
60
61         fn main() {
62             let x = foo!(1,2);
63         }
64         "#,
65         expect![[r#"
66             !0..17 '{Foo(v...,2,])}': Foo
67             !1..4 'Foo': Foo({unknown}) -> Foo
68             !1..16 'Foo(vec![1,2,])': Foo
69             !5..15 'vec![1,2,]': {unknown}
70             155..181 '{     ...,2); }': ()
71             165..166 'x': Foo
72         "#]],
73     );
74 }
75
76 #[test]
77 fn infer_legacy_textual_scoped_macros_expanded() {
78     check_infer(
79         r#"
80         struct Foo(Vec<i32>);
81
82         #[macro_use]
83         mod m {
84             macro_rules! foo {
85                 ($($item:expr),*) => {
86                     {
87                         Foo(vec![$($item,)*])
88                     }
89                 };
90             }
91         }
92
93         fn main() {
94             let x = foo!(1,2);
95             let y = crate::foo!(1,2);
96         }
97         "#,
98         expect![[r#"
99             !0..17 '{Foo(v...,2,])}': Foo
100             !1..4 'Foo': Foo({unknown}) -> Foo
101             !1..16 'Foo(vec![1,2,])': Foo
102             !5..15 'vec![1,2,]': {unknown}
103             194..250 '{     ...,2); }': ()
104             204..205 'x': Foo
105             227..228 'y': {unknown}
106             231..247 'crate:...!(1,2)': {unknown}
107         "#]],
108     );
109 }
110
111 #[test]
112 fn infer_path_qualified_macros_expanded() {
113     check_infer(
114         r#"
115         #[macro_export]
116         macro_rules! foo {
117             () => { 42i32 }
118         }
119
120         mod m {
121             pub use super::foo as bar;
122         }
123
124         fn main() {
125             let x = crate::foo!();
126             let y = m::bar!();
127         }
128         "#,
129         expect![[r#"
130             !0..5 '42i32': i32
131             !0..5 '42i32': i32
132             110..163 '{     ...!(); }': ()
133             120..121 'x': i32
134             147..148 'y': i32
135         "#]],
136     );
137 }
138
139 #[test]
140 fn expr_macro_expanded_in_various_places() {
141     check_infer(
142         r#"
143         macro_rules! spam {
144             () => (1isize);
145         }
146
147         fn spam() {
148             spam!();
149             (spam!());
150             spam!().spam(spam!());
151             for _ in spam!() {}
152             || spam!();
153             while spam!() {}
154             break spam!();
155             return spam!();
156             match spam!() {
157                 _ if spam!() => spam!(),
158             }
159             spam!()(spam!());
160             Spam { spam: spam!() };
161             spam!()[spam!()];
162             await spam!();
163             spam!() as usize;
164             &spam!();
165             -spam!();
166             spam!()..spam!();
167             spam!() + spam!();
168         }
169         "#,
170         expect![[r#"
171             !0..6 '1isize': isize
172             !0..6 '1isize': isize
173             !0..6 '1isize': isize
174             !0..6 '1isize': isize
175             !0..6 '1isize': isize
176             !0..6 '1isize': isize
177             !0..6 '1isize': isize
178             !0..6 '1isize': isize
179             !0..6 '1isize': isize
180             !0..6 '1isize': isize
181             !0..6 '1isize': isize
182             !0..6 '1isize': isize
183             !0..6 '1isize': isize
184             !0..6 '1isize': isize
185             !0..6 '1isize': isize
186             !0..6 '1isize': isize
187             !0..6 '1isize': isize
188             !0..6 '1isize': isize
189             !0..6 '1isize': isize
190             !0..6 '1isize': isize
191             !0..6 '1isize': isize
192             !0..6 '1isize': isize
193             !0..6 '1isize': isize
194             !0..6 '1isize': isize
195             !0..6 '1isize': isize
196             53..456 '{     ...!(); }': ()
197             87..108 'spam!(...am!())': {unknown}
198             114..133 'for _ ...!() {}': ()
199             118..119 '_': {unknown}
200             131..133 '{}': ()
201             138..148 '|| spam!()': || -> isize
202             154..170 'while ...!() {}': ()
203             168..170 '{}': ()
204             175..188 'break spam!()': !
205             194..208 'return spam!()': !
206             214..268 'match ...     }': isize
207             238..239 '_': isize
208             273..289 'spam!(...am!())': {unknown}
209             295..317 'Spam {...m!() }': {unknown}
210             323..339 'spam!(...am!()]': {unknown}
211             364..380 'spam!(... usize': usize
212             386..394 '&spam!()': &isize
213             400..408 '-spam!()': isize
214             414..430 'spam!(...pam!()': {unknown}
215             436..453 'spam!(...pam!()': isize
216         "#]],
217     );
218 }
219
220 #[test]
221 fn infer_type_value_macro_having_same_name() {
222     check_infer(
223         r#"
224         #[macro_export]
225         macro_rules! foo {
226             () => {
227                 mod foo {
228                     pub use super::foo;
229                 }
230             };
231             ($x:tt) => {
232                 $x
233             };
234         }
235
236         foo!();
237
238         fn foo() {
239             let foo = foo::foo!(42i32);
240         }
241         "#,
242         expect![[r#"
243             !0..5 '42i32': i32
244             170..205 '{     ...32); }': ()
245             180..183 'foo': i32
246         "#]],
247     );
248 }
249
250 #[test]
251 fn processes_impls_generated_by_macros() {
252     check_types(
253         r#"
254 macro_rules! m {
255     ($ident:ident) => (impl Trait for $ident {})
256 }
257 trait Trait { fn foo(self) -> u128 {} }
258 struct S;
259 m!(S);
260 fn test() { S.foo(); }
261                 //^ u128
262 "#,
263     );
264 }
265
266 #[test]
267 fn infer_assoc_items_generated_by_macros() {
268     check_types(
269         r#"
270 macro_rules! m {
271     () => (fn foo(&self) -> u128 {0})
272 }
273 struct S;
274 impl S {
275     m!();
276 }
277
278 fn test() { S.foo(); }
279                 //^ u128
280 "#,
281     );
282 }
283
284 #[test]
285 fn infer_assoc_items_generated_by_macros_chain() {
286     check_types(
287         r#"
288 macro_rules! m_inner {
289     () => {fn foo(&self) -> u128 {0}}
290 }
291 macro_rules! m {
292     () => {m_inner!();}
293 }
294
295 struct S;
296 impl S {
297     m!();
298 }
299
300 fn test() { S.foo(); }
301                 //^ u128
302 "#,
303     );
304 }
305
306 #[test]
307 fn infer_macro_with_dollar_crate_is_correct_in_expr() {
308     check_types(
309         r#"
310 //- /main.rs crate:main deps:foo
311 fn test() {
312     let x = (foo::foo!(1), foo::foo!(2));
313     x;
314 } //^ (i32, usize)
315
316 //- /lib.rs crate:foo
317 #[macro_export]
318 macro_rules! foo {
319     (1) => { $crate::bar!() };
320     (2) => { 1 + $crate::baz() };
321 }
322
323 #[macro_export]
324 macro_rules! bar {
325     () => { 42 }
326 }
327
328 pub fn baz() -> usize { 31usize }
329 "#,
330     );
331 }
332
333 #[test]
334 fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() {
335     check_types(
336         r#"
337 //- /main.rs crate:main deps:foo
338 use foo::Trait;
339
340 fn test() {
341     let msg = foo::Message(foo::MessageRef);
342     let r = msg.deref();
343     r;
344   //^ &MessageRef
345 }
346
347 //- /lib.rs crate:foo
348 pub struct MessageRef;
349 pub struct Message(MessageRef);
350
351 pub trait Trait {
352     type Target;
353     fn deref(&self) -> &Self::Target;
354 }
355
356 #[macro_export]
357 macro_rules! expand {
358     () => {
359         impl Trait for Message {
360             type Target = $crate::MessageRef;
361             fn deref(&self) ->  &Self::Target {
362                 &self.0
363             }
364         }
365     }
366 }
367
368 expand!();
369 "#,
370     );
371 }
372
373 #[test]
374 fn infer_type_value_non_legacy_macro_use_as() {
375     check_infer(
376         r#"
377         mod m {
378             macro_rules! _foo {
379                 ($x:ident) => { type $x = u64; }
380             }
381             pub(crate) use _foo as foo;
382         }
383
384         m::foo!(foo);
385         use foo as bar;
386         fn f() -> bar { 0 }
387         fn main() {
388             let _a  = f();
389         }
390         "#,
391         expect![[r#"
392             158..163 '{ 0 }': u64
393             160..161 '0': u64
394             174..196 '{     ...f(); }': ()
395             184..186 '_a': u64
396             190..191 'f': fn f() -> u64
397             190..193 'f()': u64
398         "#]],
399     );
400 }
401
402 #[test]
403 fn infer_local_macro() {
404     check_infer(
405         r#"
406         fn main() {
407             macro_rules! foo {
408                 () => { 1usize }
409             }
410             let _a  = foo!();
411         }
412         "#,
413         expect![[r#"
414             !0..6 '1usize': usize
415             10..89 '{     ...!(); }': ()
416             16..65 'macro_...     }': {unknown}
417             74..76 '_a': usize
418         "#]],
419     );
420 }
421
422 #[test]
423 fn infer_local_inner_macros() {
424     check_types(
425         r#"
426 //- /main.rs crate:main deps:foo
427 fn test() {
428     let x = foo::foo!(1);
429     x;
430 } //^ i32
431
432 //- /lib.rs crate:foo
433 #[macro_export(local_inner_macros)]
434 macro_rules! foo {
435     (1) => { bar!() };
436 }
437
438 #[macro_export]
439 macro_rules! bar {
440     () => { 42 }
441 }
442
443 "#,
444     );
445 }
446
447 #[test]
448 fn infer_builtin_macros_line() {
449     check_infer(
450         r#"
451         #[rustc_builtin_macro]
452         macro_rules! line {() => {}}
453
454         fn main() {
455             let x = line!();
456         }
457         "#,
458         expect![[r#"
459             !0..1 '0': i32
460             63..87 '{     ...!(); }': ()
461             73..74 'x': i32
462         "#]],
463     );
464 }
465
466 #[test]
467 fn infer_builtin_macros_file() {
468     check_infer(
469         r#"
470         #[rustc_builtin_macro]
471         macro_rules! file {() => {}}
472
473         fn main() {
474             let x = file!();
475         }
476         "#,
477         expect![[r#"
478             !0..2 '""': &str
479             63..87 '{     ...!(); }': ()
480             73..74 'x': &str
481         "#]],
482     );
483 }
484
485 #[test]
486 fn infer_builtin_macros_column() {
487     check_infer(
488         r#"
489         #[rustc_builtin_macro]
490         macro_rules! column {() => {}}
491
492         fn main() {
493             let x = column!();
494         }
495         "#,
496         expect![[r#"
497             !0..1 '0': i32
498             65..91 '{     ...!(); }': ()
499             75..76 'x': i32
500         "#]],
501     );
502 }
503
504 #[test]
505 fn infer_builtin_macros_concat() {
506     check_infer(
507         r#"
508         #[rustc_builtin_macro]
509         macro_rules! concat {() => {}}
510
511         fn main() {
512             let x = concat!("hello", concat!("world", "!"));
513         }
514         "#,
515         expect![[r#"
516             !0..13 '"helloworld!"': &str
517             65..121 '{     ...")); }': ()
518             75..76 'x': &str
519         "#]],
520     );
521 }
522
523 #[test]
524 fn infer_builtin_macros_include() {
525     check_types(
526         r#"
527 //- /main.rs
528 #[rustc_builtin_macro]
529 macro_rules! include {() => {}}
530
531 include!("foo.rs");
532
533 fn main() {
534     bar();
535 }     //^ u32
536
537 //- /foo.rs
538 fn bar() -> u32 {0}
539 "#,
540     );
541 }
542
543 #[test]
544 #[ignore]
545 fn include_accidentally_quadratic() {
546     let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic");
547     let big_file = fs::read_to_string(file).unwrap();
548     let big_file = vec![big_file; 10].join("\n");
549
550     let fixture = r#"
551 //- /main.rs
552 #[rustc_builtin_macro]
553 macro_rules! include {() => {}}
554
555 include!("foo.rs");
556
557 fn main() {
558     RegisterBlock { };
559                   //^ RegisterBlock
560 }
561     "#;
562     let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file);
563     check_types(&fixture);
564 }
565
566 #[test]
567 fn infer_builtin_macros_include_concat() {
568     check_types(
569         r#"
570 //- /main.rs
571 #[rustc_builtin_macro]
572 macro_rules! include {() => {}}
573
574 #[rustc_builtin_macro]
575 macro_rules! concat {() => {}}
576
577 include!(concat!("f", "oo.rs"));
578
579 fn main() {
580     bar();
581 }     //^ u32
582
583 //- /foo.rs
584 fn bar() -> u32 {0}
585 "#,
586     );
587 }
588
589 #[test]
590 fn infer_builtin_macros_include_concat_with_bad_env_should_failed() {
591     check_types(
592         r#"
593 //- /main.rs
594 #[rustc_builtin_macro]
595 macro_rules! include {() => {}}
596
597 #[rustc_builtin_macro]
598 macro_rules! concat {() => {}}
599
600 #[rustc_builtin_macro]
601 macro_rules! env {() => {}}
602
603 include!(concat!(env!("OUT_DIR"), "/foo.rs"));
604
605 fn main() {
606     bar();
607 }     //^ {unknown}
608
609 //- /foo.rs
610 fn bar() -> u32 {0}
611 "#,
612     );
613 }
614
615 #[test]
616 fn infer_builtin_macros_include_itself_should_failed() {
617     check_types(
618         r#"
619 #[rustc_builtin_macro]
620 macro_rules! include {() => {}}
621
622 include!("main.rs");
623
624 fn main() {
625             0
626 } //^ i32
627 "#,
628     );
629 }
630
631 #[test]
632 fn infer_builtin_macros_concat_with_lazy() {
633     check_infer(
634         r#"
635         macro_rules! hello {() => {"hello"}}
636
637         #[rustc_builtin_macro]
638         macro_rules! concat {() => {}}
639
640         fn main() {
641             let x = concat!(hello!(), concat!("world", "!"));
642         }
643         "#,
644         expect![[r#"
645             !0..13 '"helloworld!"': &str
646             103..160 '{     ...")); }': ()
647             113..114 'x': &str
648         "#]],
649     );
650 }
651
652 #[test]
653 fn infer_builtin_macros_env() {
654     check_infer(
655         r#"
656         //- /main.rs env:foo=bar
657         #[rustc_builtin_macro]
658         macro_rules! env {() => {}}
659
660         fn main() {
661             let x = env!("foo");
662         }
663         "#,
664         expect![[r#"
665             !0..22 '"__RA_...TED__"': &str
666             62..90 '{     ...o"); }': ()
667             72..73 'x': &str
668         "#]],
669     );
670 }
671
672 #[test]
673 fn infer_derive_clone_simple() {
674     check_types(
675         r#"
676 //- /main.rs crate:main deps:core
677 #[derive(Clone)]
678 struct S;
679 fn test() {
680     S.clone();
681 }         //^ S
682
683 //- /lib.rs crate:core
684 #[prelude_import]
685 use clone::*;
686 mod clone {
687     trait Clone {
688         fn clone(&self) -> Self;
689     }
690 }
691 "#,
692     );
693 }
694
695 #[test]
696 fn infer_derive_clone_in_core() {
697     check_types(
698         r#"
699 //- /lib.rs crate:core
700 #[prelude_import]
701 use clone::*;
702 mod clone {
703     trait Clone {
704         fn clone(&self) -> Self;
705     }
706 }
707 #[derive(Clone)]
708 pub struct S;
709
710 //- /main.rs crate:main deps:core
711 use core::S;
712 fn test() {
713     S.clone();
714 }         //^ S
715 "#,
716     );
717 }
718
719 #[test]
720 fn infer_derive_clone_with_params() {
721     check_types(
722         r#"
723 //- /main.rs crate:main deps:core
724 #[derive(Clone)]
725 struct S;
726 #[derive(Clone)]
727 struct Wrapper<T>(T);
728 struct NonClone;
729 fn test() {
730     (Wrapper(S).clone(), Wrapper(NonClone).clone());
731   //^ (Wrapper<S>, {unknown})
732 }
733
734 //- /lib.rs crate:core
735 #[prelude_import]
736 use clone::*;
737 mod clone {
738     trait Clone {
739         fn clone(&self) -> Self;
740     }
741 }
742 "#,
743     );
744 }
745
746 #[test]
747 fn infer_custom_derive_simple() {
748     // FIXME: this test current now do nothing
749     check_types(
750         r#"
751 //- /main.rs crate:main
752 use foo::Foo;
753
754 #[derive(Foo)]
755 struct S{}
756
757 fn test() {
758     S{};
759 }   //^ S
760 "#,
761     );
762 }
763
764 #[test]
765 fn macro_in_arm() {
766     check_infer(
767         r#"
768         macro_rules! unit {
769             () => { () };
770         }
771
772         fn main() {
773             let x = match () {
774                 unit!() => 92u32,
775             };
776         }
777         "#,
778         expect![[r#"
779             51..110 '{     ...  }; }': ()
780             61..62 'x': u32
781             65..107 'match ...     }': u32
782             71..73 '()': ()
783             84..91 'unit!()': ()
784             95..100 '92u32': u32
785         "#]],
786     );
787 }