]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/macros.rs
Fix recursive macro statement expansion
[rust.git] / crates / hir_ty / src / tests / macros.rs
1 use expect_test::expect;
2 use test_utils::{bench, bench_fixture, skip_slow_tests};
3
4 use super::{check_infer, check_types};
5
6 #[test]
7 fn cfg_impl_def() {
8     check_types(
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 } //^ (i32, {unknown}, i32, {unknown})
28
29 //- /foo.rs crate:foo
30 struct S;
31
32 #[cfg(not(test))]
33 impl S {
34     pub fn foo3(&self) -> i32 { 0 }
35 }
36
37 #[cfg(test)]
38 impl S {
39     pub fn foo4(&self) -> i32 { 0 }
40 }
41 "#,
42     );
43 }
44
45 #[test]
46 fn infer_macros_expanded() {
47     check_infer(
48         r#"
49         struct Foo(Vec<i32>);
50
51         macro_rules! foo {
52             ($($item:expr),*) => {
53                     {
54                         Foo(vec![$($item,)*])
55                     }
56             };
57         }
58
59         fn main() {
60             let x = foo!(1,2);
61         }
62         "#,
63         expect![[r#"
64             !0..17 '{Foo(v...,2,])}': Foo
65             !1..4 'Foo': Foo({unknown}) -> Foo
66             !1..16 'Foo(vec![1,2,])': Foo
67             !5..15 'vec![1,2,]': {unknown}
68             155..181 '{     ...,2); }': ()
69             165..166 'x': Foo
70         "#]],
71     );
72 }
73
74 #[test]
75 fn infer_legacy_textual_scoped_macros_expanded() {
76     check_infer(
77         r#"
78         struct Foo(Vec<i32>);
79
80         #[macro_use]
81         mod m {
82             macro_rules! foo {
83                 ($($item:expr),*) => {
84                     {
85                         Foo(vec![$($item,)*])
86                     }
87                 };
88             }
89         }
90
91         fn main() {
92             let x = foo!(1,2);
93             let y = crate::foo!(1,2);
94         }
95         "#,
96         expect![[r#"
97             !0..17 '{Foo(v...,2,])}': Foo
98             !1..4 'Foo': Foo({unknown}) -> Foo
99             !1..16 'Foo(vec![1,2,])': Foo
100             !5..15 'vec![1,2,]': {unknown}
101             194..250 '{     ...,2); }': ()
102             204..205 'x': Foo
103             227..228 'y': {unknown}
104             231..247 'crate:...!(1,2)': {unknown}
105         "#]],
106     );
107 }
108
109 #[test]
110 fn infer_path_qualified_macros_expanded() {
111     check_infer(
112         r#"
113         #[macro_export]
114         macro_rules! foo {
115             () => { 42i32 }
116         }
117
118         mod m {
119             pub use super::foo as bar;
120         }
121
122         fn main() {
123             let x = crate::foo!();
124             let y = m::bar!();
125         }
126         "#,
127         expect![[r#"
128             !0..5 '42i32': i32
129             !0..5 '42i32': i32
130             110..163 '{     ...!(); }': ()
131             120..121 'x': i32
132             147..148 'y': i32
133         "#]],
134     );
135 }
136
137 #[test]
138 fn expr_macro_expanded_in_various_places() {
139     check_infer(
140         r#"
141         macro_rules! spam {
142             () => (1isize);
143         }
144
145         fn spam() {
146             spam!();
147             (spam!());
148             spam!().spam(spam!());
149             for _ in spam!() {}
150             || spam!();
151             while spam!() {}
152             break spam!();
153             return spam!();
154             match spam!() {
155                 _ if spam!() => spam!(),
156             }
157             spam!()(spam!());
158             Spam { spam: spam!() };
159             spam!()[spam!()];
160             await spam!();
161             spam!() as usize;
162             &spam!();
163             -spam!();
164             spam!()..spam!();
165             spam!() + spam!();
166         }
167         "#,
168         expect![[r#"
169             !0..6 '1isize': isize
170             !0..6 '1isize': isize
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             53..456 '{     ...!(); }': ()
195             87..108 'spam!(...am!())': {unknown}
196             114..133 'for _ ...!() {}': ()
197             118..119 '_': {unknown}
198             131..133 '{}': ()
199             138..148 '|| spam!()': || -> isize
200             154..170 'while ...!() {}': ()
201             168..170 '{}': ()
202             175..188 'break spam!()': !
203             194..208 'return spam!()': !
204             214..268 'match ...     }': isize
205             238..239 '_': isize
206             273..289 'spam!(...am!())': {unknown}
207             295..317 'Spam {...m!() }': {unknown}
208             323..339 'spam!(...am!()]': {unknown}
209             364..380 'spam!(... usize': usize
210             386..394 '&spam!()': &isize
211             400..408 '-spam!()': isize
212             414..430 'spam!(...pam!()': {unknown}
213             436..453 'spam!(...pam!()': isize
214         "#]],
215     );
216 }
217
218 #[test]
219 fn expr_macro_expanded_in_stmts() {
220     check_infer(
221         r#"
222         macro_rules! id { ($($es:tt)*) => { $($es)* } }
223         fn foo() {
224             id! { let a = (); }
225         }
226         "#,
227         expect![[r#"
228             !0..8 'leta=();': ()
229             !0..8 'leta=();': ()
230             !3..4 'a': ()
231             !5..7 '()': ()
232             57..84 '{     ...); } }': ()
233         "#]],
234     );
235 }
236
237 #[test]
238 fn recurisve_macro_expanded_in_stmts() {
239     check_infer(
240         r#"
241         macro_rules! ng {
242             ([$($tts:tt)*]) => {
243                 $($tts)*;
244             };
245             ([$($tts:tt)*] $head:tt $($rest:tt)*) => {
246                 ng! {
247                     [$($tts)* $head] $($rest)*
248                 }
249             };
250         }
251         fn foo() {
252             ng!([] let a = 3);
253             let b = a;
254         }
255         "#,
256         expect![[r#"
257             !0..7 'leta=3;': {unknown}
258             !0..7 'leta=3;': {unknown}
259             !0..13 'ng!{[leta=3]}': {unknown}
260             !0..13 'ng!{[leta=]3}': {unknown}
261             !0..13 'ng!{[leta]=3}': {unknown}
262             !3..4 'a': i32
263             !5..6 '3': i32
264             196..237 '{     ...= a; }': ()
265             229..230 'b': i32
266             233..234 'a': i32
267         "#]],
268     );
269 }
270
271 #[test]
272 fn recursive_inner_item_macro_rules() {
273     check_infer(
274         r#"
275         macro_rules! mac {
276             () => { mac!($)};
277             ($x:tt) => { macro_rules! blub { () => { 1 }; } };
278         }
279         fn foo() {
280             mac!();
281             let a = blub!();
282         }
283         "#,
284         expect![[r#"
285             !0..1 '1': i32
286             !0..26 'macro_...>{1};}': {unknown}
287             !0..26 'macro_...>{1};}': {unknown}
288             107..143 '{     ...!(); }': ()
289             129..130 'a': i32
290         "#]],
291     );
292 }
293
294 #[test]
295 fn infer_type_value_macro_having_same_name() {
296     check_infer(
297         r#"
298         #[macro_export]
299         macro_rules! foo {
300             () => {
301                 mod foo {
302                     pub use super::foo;
303                 }
304             };
305             ($x:tt) => {
306                 $x
307             };
308         }
309
310         foo!();
311
312         fn foo() {
313             let foo = foo::foo!(42i32);
314         }
315         "#,
316         expect![[r#"
317             !0..5 '42i32': i32
318             170..205 '{     ...32); }': ()
319             180..183 'foo': i32
320         "#]],
321     );
322 }
323
324 #[test]
325 fn processes_impls_generated_by_macros() {
326     check_types(
327         r#"
328 macro_rules! m {
329     ($ident:ident) => (impl Trait for $ident {})
330 }
331 trait Trait { fn foo(self) -> u128 {} }
332 struct S;
333 m!(S);
334 fn test() { S.foo(); }
335                 //^ u128
336 "#,
337     );
338 }
339
340 #[test]
341 fn infer_assoc_items_generated_by_macros() {
342     check_types(
343         r#"
344 macro_rules! m {
345     () => (fn foo(&self) -> u128 {0})
346 }
347 struct S;
348 impl S {
349     m!();
350 }
351
352 fn test() { S.foo(); }
353                 //^ u128
354 "#,
355     );
356 }
357
358 #[test]
359 fn infer_assoc_items_generated_by_macros_chain() {
360     check_types(
361         r#"
362 macro_rules! m_inner {
363     () => {fn foo(&self) -> u128 {0}}
364 }
365 macro_rules! m {
366     () => {m_inner!();}
367 }
368
369 struct S;
370 impl S {
371     m!();
372 }
373
374 fn test() { S.foo(); }
375                 //^ u128
376 "#,
377     );
378 }
379
380 #[test]
381 fn infer_macro_with_dollar_crate_is_correct_in_expr() {
382     check_types(
383         r#"
384 //- /main.rs crate:main deps:foo
385 fn test() {
386     let x = (foo::foo!(1), foo::foo!(2));
387     x;
388 } //^ (i32, usize)
389
390 //- /lib.rs crate:foo
391 #[macro_export]
392 macro_rules! foo {
393     (1) => { $crate::bar!() };
394     (2) => { 1 + $crate::baz() };
395 }
396
397 #[macro_export]
398 macro_rules! bar {
399     () => { 42 }
400 }
401
402 pub fn baz() -> usize { 31usize }
403 "#,
404     );
405 }
406
407 #[test]
408 fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() {
409     check_types(
410         r#"
411 //- /main.rs crate:main deps:foo
412 use foo::Trait;
413
414 fn test() {
415     let msg = foo::Message(foo::MessageRef);
416     let r = msg.deref();
417     r;
418   //^ &MessageRef
419 }
420
421 //- /lib.rs crate:foo
422 pub struct MessageRef;
423 pub struct Message(MessageRef);
424
425 pub trait Trait {
426     type Target;
427     fn deref(&self) -> &Self::Target;
428 }
429
430 #[macro_export]
431 macro_rules! expand {
432     () => {
433         impl Trait for Message {
434             type Target = $crate::MessageRef;
435             fn deref(&self) ->  &Self::Target {
436                 &self.0
437             }
438         }
439     }
440 }
441
442 expand!();
443 "#,
444     );
445 }
446
447 #[test]
448 fn infer_macro_with_dollar_crate_in_def_site() {
449     check_types(
450         r#"
451 //- /main.rs crate:main deps:foo
452 use foo::expand;
453
454 macro_rules! list {
455     ($($tt:tt)*) => { $($tt)* }
456 }
457
458 fn test() {
459     let r = expand!();
460     r;
461   //^ u128
462 }
463
464 //- /lib.rs crate:foo
465 #[macro_export]
466 macro_rules! expand {
467     () => { list!($crate::m!()) };
468 }
469
470 #[macro_export]
471 macro_rules! m {
472     () => { 0u128 };
473 }
474 "#,
475     );
476 }
477
478 #[test]
479 fn infer_type_value_non_legacy_macro_use_as() {
480     check_infer(
481         r#"
482         mod m {
483             macro_rules! _foo {
484                 ($x:ident) => { type $x = u64; }
485             }
486             pub(crate) use _foo as foo;
487         }
488
489         m::foo!(foo);
490         use foo as bar;
491         fn f() -> bar { 0 }
492         fn main() {
493             let _a  = f();
494         }
495         "#,
496         expect![[r#"
497             158..163 '{ 0 }': u64
498             160..161 '0': u64
499             174..196 '{     ...f(); }': ()
500             184..186 '_a': u64
501             190..191 'f': fn f() -> u64
502             190..193 'f()': u64
503         "#]],
504     );
505 }
506
507 #[test]
508 fn infer_local_macro() {
509     check_infer(
510         r#"
511         fn main() {
512             macro_rules! foo {
513                 () => { 1usize }
514             }
515             let _a  = foo!();
516         }
517         "#,
518         expect![[r#"
519             !0..6 '1usize': usize
520             10..89 '{     ...!(); }': ()
521             74..76 '_a': usize
522         "#]],
523     );
524 }
525
526 #[test]
527 fn infer_local_inner_macros() {
528     check_types(
529         r#"
530 //- /main.rs crate:main deps:foo
531 fn test() {
532     let x = foo::foo!(1);
533     x;
534 } //^ i32
535
536 //- /lib.rs crate:foo
537 #[macro_export(local_inner_macros)]
538 macro_rules! foo {
539     (1) => { bar!() };
540 }
541
542 #[macro_export]
543 macro_rules! bar {
544     () => { 42 }
545 }
546
547 "#,
548     );
549 }
550
551 #[test]
552 fn infer_builtin_macros_line() {
553     check_infer(
554         r#"
555         #[rustc_builtin_macro]
556         macro_rules! line {() => {}}
557
558         fn main() {
559             let x = line!();
560         }
561         "#,
562         expect![[r#"
563             !0..1 '0': i32
564             63..87 '{     ...!(); }': ()
565             73..74 'x': i32
566         "#]],
567     );
568 }
569
570 #[test]
571 fn infer_builtin_macros_file() {
572     check_infer(
573         r#"
574         #[rustc_builtin_macro]
575         macro_rules! file {() => {}}
576
577         fn main() {
578             let x = file!();
579         }
580         "#,
581         expect![[r#"
582             !0..2 '""': &str
583             63..87 '{     ...!(); }': ()
584             73..74 'x': &str
585         "#]],
586     );
587 }
588
589 #[test]
590 fn infer_builtin_macros_column() {
591     check_infer(
592         r#"
593         #[rustc_builtin_macro]
594         macro_rules! column {() => {}}
595
596         fn main() {
597             let x = column!();
598         }
599         "#,
600         expect![[r#"
601             !0..1 '0': i32
602             65..91 '{     ...!(); }': ()
603             75..76 'x': i32
604         "#]],
605     );
606 }
607
608 #[test]
609 fn infer_builtin_macros_concat() {
610     check_infer(
611         r#"
612         #[rustc_builtin_macro]
613         macro_rules! concat {() => {}}
614
615         fn main() {
616             let x = concat!("hello", concat!("world", "!"));
617         }
618         "#,
619         expect![[r#"
620             !0..13 '"helloworld!"': &str
621             65..121 '{     ...")); }': ()
622             75..76 'x': &str
623         "#]],
624     );
625 }
626
627 #[test]
628 fn infer_builtin_macros_include() {
629     check_types(
630         r#"
631 //- /main.rs
632 #[rustc_builtin_macro]
633 macro_rules! include {() => {}}
634
635 include!("foo.rs");
636
637 fn main() {
638     bar();
639 }     //^ u32
640
641 //- /foo.rs
642 fn bar() -> u32 {0}
643 "#,
644     );
645 }
646
647 #[test]
648 fn infer_builtin_macros_include_child_mod() {
649     check_types(
650         r#"
651 //- /main.rs
652 #[rustc_builtin_macro]
653 macro_rules! include {() => {}}
654
655 include!("f/foo.rs");
656
657 fn main() {
658     bar::bar();
659 }          //^ u32
660
661 //- /f/foo.rs
662 pub mod bar;
663
664 //- /f/bar.rs
665 pub fn bar() -> u32 {0}
666 "#,
667     );
668 }
669
670 #[test]
671 fn infer_builtin_macros_include_str() {
672     check_types(
673         r#"
674 //- /main.rs
675 #[rustc_builtin_macro]
676 macro_rules! include_str {() => {}}
677
678 fn main() {
679     let a = include_str!("foo.rs");
680     a;
681 } //^ &str
682
683 //- /foo.rs
684 hello
685 "#,
686     );
687 }
688
689 #[test]
690 fn infer_builtin_macros_include_str_with_lazy_nested() {
691     check_types(
692         r#"
693 //- /main.rs
694 #[rustc_builtin_macro]
695 macro_rules! concat {() => {}}
696 #[rustc_builtin_macro]
697 macro_rules! include_str {() => {}}
698
699 macro_rules! m {
700     ($x:expr) => {
701         concat!("foo", $x)
702     };
703 }
704
705 fn main() {
706     let a = include_str!(m!(".rs"));
707     a;
708 } //^ &str
709
710 //- /foo.rs
711 hello
712 "#,
713     );
714 }
715
716 #[test]
717 fn benchmark_include_macro() {
718     if skip_slow_tests() {
719         return;
720     }
721     let data = bench_fixture::big_struct();
722     let fixture = r#"
723 //- /main.rs
724 #[rustc_builtin_macro]
725 macro_rules! include {() => {}}
726
727 include!("foo.rs");
728
729 fn main() {
730     RegisterBlock { };
731                   //^ RegisterBlock
732 }
733     "#;
734     let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data);
735
736     {
737         let _b = bench("include macro");
738         check_types(&fixture);
739     }
740 }
741
742 #[test]
743 fn infer_builtin_macros_include_concat() {
744     check_types(
745         r#"
746 //- /main.rs
747 #[rustc_builtin_macro]
748 macro_rules! include {() => {}}
749
750 #[rustc_builtin_macro]
751 macro_rules! concat {() => {}}
752
753 include!(concat!("f", "oo.rs"));
754
755 fn main() {
756     bar();
757 }     //^ u32
758
759 //- /foo.rs
760 fn bar() -> u32 {0}
761 "#,
762     );
763 }
764
765 #[test]
766 fn infer_builtin_macros_include_concat_with_bad_env_should_failed() {
767     check_types(
768         r#"
769 //- /main.rs
770 #[rustc_builtin_macro]
771 macro_rules! include {() => {}}
772
773 #[rustc_builtin_macro]
774 macro_rules! concat {() => {}}
775
776 #[rustc_builtin_macro]
777 macro_rules! env {() => {}}
778
779 include!(concat!(env!("OUT_DIR"), "/foo.rs"));
780
781 fn main() {
782     bar();
783 }     //^ {unknown}
784
785 //- /foo.rs
786 fn bar() -> u32 {0}
787 "#,
788     );
789 }
790
791 #[test]
792 fn infer_builtin_macros_include_itself_should_failed() {
793     check_types(
794         r#"
795 #[rustc_builtin_macro]
796 macro_rules! include {() => {}}
797
798 include!("main.rs");
799
800 fn main() {
801             0
802 } //^ i32
803 "#,
804     );
805 }
806
807 #[test]
808 fn infer_builtin_macros_concat_with_lazy() {
809     check_infer(
810         r#"
811         macro_rules! hello {() => {"hello"}}
812
813         #[rustc_builtin_macro]
814         macro_rules! concat {() => {}}
815
816         fn main() {
817             let x = concat!(hello!(), concat!("world", "!"));
818         }
819         "#,
820         expect![[r#"
821             !0..13 '"helloworld!"': &str
822             103..160 '{     ...")); }': ()
823             113..114 'x': &str
824         "#]],
825     );
826 }
827
828 #[test]
829 fn infer_builtin_macros_env() {
830     check_infer(
831         r#"
832         //- /main.rs env:foo=bar
833         #[rustc_builtin_macro]
834         macro_rules! env {() => {}}
835
836         fn main() {
837             let x = env!("foo");
838         }
839         "#,
840         expect![[r#"
841             !0..22 '"__RA_...TED__"': &str
842             62..90 '{     ...o"); }': ()
843             72..73 'x': &str
844         "#]],
845     );
846 }
847
848 #[test]
849 fn infer_derive_clone_simple() {
850     check_types(
851         r#"
852 //- /main.rs crate:main deps:core
853 #[derive(Clone)]
854 struct S;
855 fn test() {
856     S.clone();
857 }         //^ S
858
859 //- /lib.rs crate:core
860 #[prelude_import]
861 use clone::*;
862 mod clone {
863     trait Clone {
864         fn clone(&self) -> Self;
865     }
866     #[rustc_builtin_macro]
867     macro Clone {}
868 }
869 "#,
870     );
871 }
872
873 #[test]
874 fn infer_derive_clone_in_core() {
875     check_types(
876         r#"
877 //- /lib.rs crate:core
878 #[prelude_import]
879 use clone::*;
880 mod clone {
881     trait Clone {
882         fn clone(&self) -> Self;
883     }
884     #[rustc_builtin_macro]
885     macro Clone {}
886 }
887 #[derive(Clone)]
888 pub struct S;
889
890 //- /main.rs crate:main deps:core
891 use core::S;
892 fn test() {
893     S.clone();
894 }         //^ S
895 "#,
896     );
897 }
898
899 #[test]
900 fn infer_derive_clone_with_params() {
901     check_types(
902         r#"
903 //- /main.rs crate:main deps:core
904 #[derive(Clone)]
905 struct S;
906 #[derive(Clone)]
907 struct Wrapper<T>(T);
908 struct NonClone;
909 fn test() {
910     (Wrapper(S).clone(), Wrapper(NonClone).clone());
911   //^ (Wrapper<S>, {unknown})
912 }
913
914 //- /lib.rs crate:core
915 #[prelude_import]
916 use clone::*;
917 mod clone {
918     trait Clone {
919         fn clone(&self) -> Self;
920     }
921     #[rustc_builtin_macro]
922     macro Clone {}
923 }
924 "#,
925     );
926 }
927
928 #[test]
929 fn infer_custom_derive_simple() {
930     // FIXME: this test current now do nothing
931     check_types(
932         r#"
933 //- /main.rs crate:main
934 use foo::Foo;
935
936 #[derive(Foo)]
937 struct S{}
938
939 fn test() {
940     S{};
941 }   //^ S
942 "#,
943     );
944 }
945
946 #[test]
947 fn macro_in_arm() {
948     check_infer(
949         r#"
950         macro_rules! unit {
951             () => { () };
952         }
953
954         fn main() {
955             let x = match () {
956                 unit!() => 92u32,
957             };
958         }
959         "#,
960         expect![[r#"
961             51..110 '{     ...  }; }': ()
962             61..62 'x': u32
963             65..107 'match ...     }': u32
964             71..73 '()': ()
965             84..91 'unit!()': ()
966             95..100 '92u32': u32
967         "#]],
968     );
969 }