]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/macros.rs
Merge #8082
[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     fn foo3(&self) -> i32 { 0 }
35 }
36
37 #[cfg(test)]
38 impl S {
39     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             57..84 '{     ...); } }': ()
230         "#]],
231     );
232 }
233
234 #[test]
235 fn recursive_inner_item_macro_rules() {
236     check_infer(
237         r#"
238         macro_rules! mac {
239             () => { mac!($)};
240             ($x:tt) => { macro_rules! blub { () => { 1 }; } };
241         }
242         fn foo() {
243             mac!();
244             let a = blub!();
245         }
246         "#,
247         expect![[r#"
248             !0..1 '1': i32
249             !0..7 'mac!($)': {unknown}
250             107..143 '{     ...!(); }': ()
251             129..130 'a': i32
252         "#]],
253     );
254 }
255
256 #[test]
257 fn infer_type_value_macro_having_same_name() {
258     check_infer(
259         r#"
260         #[macro_export]
261         macro_rules! foo {
262             () => {
263                 mod foo {
264                     pub use super::foo;
265                 }
266             };
267             ($x:tt) => {
268                 $x
269             };
270         }
271
272         foo!();
273
274         fn foo() {
275             let foo = foo::foo!(42i32);
276         }
277         "#,
278         expect![[r#"
279             !0..5 '42i32': i32
280             170..205 '{     ...32); }': ()
281             180..183 'foo': i32
282         "#]],
283     );
284 }
285
286 #[test]
287 fn processes_impls_generated_by_macros() {
288     check_types(
289         r#"
290 macro_rules! m {
291     ($ident:ident) => (impl Trait for $ident {})
292 }
293 trait Trait { fn foo(self) -> u128 {} }
294 struct S;
295 m!(S);
296 fn test() { S.foo(); }
297                 //^ u128
298 "#,
299     );
300 }
301
302 #[test]
303 fn infer_assoc_items_generated_by_macros() {
304     check_types(
305         r#"
306 macro_rules! m {
307     () => (fn foo(&self) -> u128 {0})
308 }
309 struct S;
310 impl S {
311     m!();
312 }
313
314 fn test() { S.foo(); }
315                 //^ u128
316 "#,
317     );
318 }
319
320 #[test]
321 fn infer_assoc_items_generated_by_macros_chain() {
322     check_types(
323         r#"
324 macro_rules! m_inner {
325     () => {fn foo(&self) -> u128 {0}}
326 }
327 macro_rules! m {
328     () => {m_inner!();}
329 }
330
331 struct S;
332 impl S {
333     m!();
334 }
335
336 fn test() { S.foo(); }
337                 //^ u128
338 "#,
339     );
340 }
341
342 #[test]
343 fn infer_macro_with_dollar_crate_is_correct_in_expr() {
344     check_types(
345         r#"
346 //- /main.rs crate:main deps:foo
347 fn test() {
348     let x = (foo::foo!(1), foo::foo!(2));
349     x;
350 } //^ (i32, usize)
351
352 //- /lib.rs crate:foo
353 #[macro_export]
354 macro_rules! foo {
355     (1) => { $crate::bar!() };
356     (2) => { 1 + $crate::baz() };
357 }
358
359 #[macro_export]
360 macro_rules! bar {
361     () => { 42 }
362 }
363
364 pub fn baz() -> usize { 31usize }
365 "#,
366     );
367 }
368
369 #[test]
370 fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() {
371     check_types(
372         r#"
373 //- /main.rs crate:main deps:foo
374 use foo::Trait;
375
376 fn test() {
377     let msg = foo::Message(foo::MessageRef);
378     let r = msg.deref();
379     r;
380   //^ &MessageRef
381 }
382
383 //- /lib.rs crate:foo
384 pub struct MessageRef;
385 pub struct Message(MessageRef);
386
387 pub trait Trait {
388     type Target;
389     fn deref(&self) -> &Self::Target;
390 }
391
392 #[macro_export]
393 macro_rules! expand {
394     () => {
395         impl Trait for Message {
396             type Target = $crate::MessageRef;
397             fn deref(&self) ->  &Self::Target {
398                 &self.0
399             }
400         }
401     }
402 }
403
404 expand!();
405 "#,
406     );
407 }
408
409 #[test]
410 fn infer_macro_with_dollar_crate_in_def_site() {
411     check_types(
412         r#"
413 //- /main.rs crate:main deps:foo
414 use foo::expand;
415
416 macro_rules! list {
417     ($($tt:tt)*) => { $($tt)* }
418 }
419
420 fn test() {
421     let r = expand!();
422     r;
423   //^ u128
424 }
425
426 //- /lib.rs crate:foo
427 #[macro_export]
428 macro_rules! expand {
429     () => { list!($crate::m!()) };
430 }
431
432 #[macro_export]
433 macro_rules! m {
434     () => { 0u128 };
435 }
436 "#,
437     );
438 }
439
440 #[test]
441 fn infer_type_value_non_legacy_macro_use_as() {
442     check_infer(
443         r#"
444         mod m {
445             macro_rules! _foo {
446                 ($x:ident) => { type $x = u64; }
447             }
448             pub(crate) use _foo as foo;
449         }
450
451         m::foo!(foo);
452         use foo as bar;
453         fn f() -> bar { 0 }
454         fn main() {
455             let _a  = f();
456         }
457         "#,
458         expect![[r#"
459             158..163 '{ 0 }': u64
460             160..161 '0': u64
461             174..196 '{     ...f(); }': ()
462             184..186 '_a': u64
463             190..191 'f': fn f() -> u64
464             190..193 'f()': u64
465         "#]],
466     );
467 }
468
469 #[test]
470 fn infer_local_macro() {
471     check_infer(
472         r#"
473         fn main() {
474             macro_rules! foo {
475                 () => { 1usize }
476             }
477             let _a  = foo!();
478         }
479         "#,
480         expect![[r#"
481             !0..6 '1usize': usize
482             10..89 '{     ...!(); }': ()
483             74..76 '_a': usize
484         "#]],
485     );
486 }
487
488 #[test]
489 fn infer_local_inner_macros() {
490     check_types(
491         r#"
492 //- /main.rs crate:main deps:foo
493 fn test() {
494     let x = foo::foo!(1);
495     x;
496 } //^ i32
497
498 //- /lib.rs crate:foo
499 #[macro_export(local_inner_macros)]
500 macro_rules! foo {
501     (1) => { bar!() };
502 }
503
504 #[macro_export]
505 macro_rules! bar {
506     () => { 42 }
507 }
508
509 "#,
510     );
511 }
512
513 #[test]
514 fn infer_builtin_macros_line() {
515     check_infer(
516         r#"
517         #[rustc_builtin_macro]
518         macro_rules! line {() => {}}
519
520         fn main() {
521             let x = line!();
522         }
523         "#,
524         expect![[r#"
525             !0..1 '0': i32
526             63..87 '{     ...!(); }': ()
527             73..74 'x': i32
528         "#]],
529     );
530 }
531
532 #[test]
533 fn infer_builtin_macros_file() {
534     check_infer(
535         r#"
536         #[rustc_builtin_macro]
537         macro_rules! file {() => {}}
538
539         fn main() {
540             let x = file!();
541         }
542         "#,
543         expect![[r#"
544             !0..2 '""': &str
545             63..87 '{     ...!(); }': ()
546             73..74 'x': &str
547         "#]],
548     );
549 }
550
551 #[test]
552 fn infer_builtin_macros_column() {
553     check_infer(
554         r#"
555         #[rustc_builtin_macro]
556         macro_rules! column {() => {}}
557
558         fn main() {
559             let x = column!();
560         }
561         "#,
562         expect![[r#"
563             !0..1 '0': i32
564             65..91 '{     ...!(); }': ()
565             75..76 'x': i32
566         "#]],
567     );
568 }
569
570 #[test]
571 fn infer_builtin_macros_concat() {
572     check_infer(
573         r#"
574         #[rustc_builtin_macro]
575         macro_rules! concat {() => {}}
576
577         fn main() {
578             let x = concat!("hello", concat!("world", "!"));
579         }
580         "#,
581         expect![[r#"
582             !0..13 '"helloworld!"': &str
583             65..121 '{     ...")); }': ()
584             75..76 'x': &str
585         "#]],
586     );
587 }
588
589 #[test]
590 fn infer_builtin_macros_include() {
591     check_types(
592         r#"
593 //- /main.rs
594 #[rustc_builtin_macro]
595 macro_rules! include {() => {}}
596
597 include!("foo.rs");
598
599 fn main() {
600     bar();
601 }     //^ u32
602
603 //- /foo.rs
604 fn bar() -> u32 {0}
605 "#,
606     );
607 }
608
609 #[test]
610 fn infer_builtin_macros_include_str() {
611     check_types(
612         r#"
613 //- /main.rs
614 #[rustc_builtin_macro]
615 macro_rules! include_str {() => {}}
616
617 fn main() {
618     let a = include_str!("foo.rs");
619     a;
620 } //^ &str
621
622 //- /foo.rs
623 hello
624 "#,
625     );
626 }
627
628 #[test]
629 fn infer_builtin_macros_include_str_with_lazy_nested() {
630     check_types(
631         r#"
632 //- /main.rs
633 #[rustc_builtin_macro]
634 macro_rules! concat {() => {}}
635 #[rustc_builtin_macro]
636 macro_rules! include_str {() => {}}
637
638 macro_rules! m {
639     ($x:expr) => {
640         concat!("foo", $x)
641     };
642 }
643
644 fn main() {
645     let a = include_str!(m!(".rs"));
646     a;
647 } //^ &str
648
649 //- /foo.rs
650 hello
651 "#,
652     );
653 }
654
655 #[test]
656 fn benchmark_include_macro() {
657     if skip_slow_tests() {
658         return;
659     }
660     let data = bench_fixture::big_struct();
661     let fixture = r#"
662 //- /main.rs
663 #[rustc_builtin_macro]
664 macro_rules! include {() => {}}
665
666 include!("foo.rs");
667
668 fn main() {
669     RegisterBlock { };
670                   //^ RegisterBlock
671 }
672     "#;
673     let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data);
674
675     {
676         let _b = bench("include macro");
677         check_types(&fixture);
678     }
679 }
680
681 #[test]
682 fn infer_builtin_macros_include_concat() {
683     check_types(
684         r#"
685 //- /main.rs
686 #[rustc_builtin_macro]
687 macro_rules! include {() => {}}
688
689 #[rustc_builtin_macro]
690 macro_rules! concat {() => {}}
691
692 include!(concat!("f", "oo.rs"));
693
694 fn main() {
695     bar();
696 }     //^ u32
697
698 //- /foo.rs
699 fn bar() -> u32 {0}
700 "#,
701     );
702 }
703
704 #[test]
705 fn infer_builtin_macros_include_concat_with_bad_env_should_failed() {
706     check_types(
707         r#"
708 //- /main.rs
709 #[rustc_builtin_macro]
710 macro_rules! include {() => {}}
711
712 #[rustc_builtin_macro]
713 macro_rules! concat {() => {}}
714
715 #[rustc_builtin_macro]
716 macro_rules! env {() => {}}
717
718 include!(concat!(env!("OUT_DIR"), "/foo.rs"));
719
720 fn main() {
721     bar();
722 }     //^ {unknown}
723
724 //- /foo.rs
725 fn bar() -> u32 {0}
726 "#,
727     );
728 }
729
730 #[test]
731 fn infer_builtin_macros_include_itself_should_failed() {
732     check_types(
733         r#"
734 #[rustc_builtin_macro]
735 macro_rules! include {() => {}}
736
737 include!("main.rs");
738
739 fn main() {
740             0
741 } //^ i32
742 "#,
743     );
744 }
745
746 #[test]
747 fn infer_builtin_macros_concat_with_lazy() {
748     check_infer(
749         r#"
750         macro_rules! hello {() => {"hello"}}
751
752         #[rustc_builtin_macro]
753         macro_rules! concat {() => {}}
754
755         fn main() {
756             let x = concat!(hello!(), concat!("world", "!"));
757         }
758         "#,
759         expect![[r#"
760             !0..13 '"helloworld!"': &str
761             103..160 '{     ...")); }': ()
762             113..114 'x': &str
763         "#]],
764     );
765 }
766
767 #[test]
768 fn infer_builtin_macros_env() {
769     check_infer(
770         r#"
771         //- /main.rs env:foo=bar
772         #[rustc_builtin_macro]
773         macro_rules! env {() => {}}
774
775         fn main() {
776             let x = env!("foo");
777         }
778         "#,
779         expect![[r#"
780             !0..22 '"__RA_...TED__"': &str
781             62..90 '{     ...o"); }': ()
782             72..73 'x': &str
783         "#]],
784     );
785 }
786
787 #[test]
788 fn infer_derive_clone_simple() {
789     check_types(
790         r#"
791 //- /main.rs crate:main deps:core
792 #[derive(Clone)]
793 struct S;
794 fn test() {
795     S.clone();
796 }         //^ S
797
798 //- /lib.rs crate:core
799 #[prelude_import]
800 use clone::*;
801 mod clone {
802     trait Clone {
803         fn clone(&self) -> Self;
804     }
805     #[rustc_builtin_macro]
806     macro Clone {}
807 }
808 "#,
809     );
810 }
811
812 #[test]
813 fn infer_derive_clone_in_core() {
814     check_types(
815         r#"
816 //- /lib.rs crate:core
817 #[prelude_import]
818 use clone::*;
819 mod clone {
820     trait Clone {
821         fn clone(&self) -> Self;
822     }
823     #[rustc_builtin_macro]
824     macro Clone {}
825 }
826 #[derive(Clone)]
827 pub struct S;
828
829 //- /main.rs crate:main deps:core
830 use core::S;
831 fn test() {
832     S.clone();
833 }         //^ S
834 "#,
835     );
836 }
837
838 #[test]
839 fn infer_derive_clone_with_params() {
840     check_types(
841         r#"
842 //- /main.rs crate:main deps:core
843 #[derive(Clone)]
844 struct S;
845 #[derive(Clone)]
846 struct Wrapper<T>(T);
847 struct NonClone;
848 fn test() {
849     (Wrapper(S).clone(), Wrapper(NonClone).clone());
850   //^ (Wrapper<S>, {unknown})
851 }
852
853 //- /lib.rs crate:core
854 #[prelude_import]
855 use clone::*;
856 mod clone {
857     trait Clone {
858         fn clone(&self) -> Self;
859     }
860     #[rustc_builtin_macro]
861     macro Clone {}
862 }
863 "#,
864     );
865 }
866
867 #[test]
868 fn infer_custom_derive_simple() {
869     // FIXME: this test current now do nothing
870     check_types(
871         r#"
872 //- /main.rs crate:main
873 use foo::Foo;
874
875 #[derive(Foo)]
876 struct S{}
877
878 fn test() {
879     S{};
880 }   //^ S
881 "#,
882     );
883 }
884
885 #[test]
886 fn macro_in_arm() {
887     check_infer(
888         r#"
889         macro_rules! unit {
890             () => { () };
891         }
892
893         fn main() {
894             let x = match () {
895                 unit!() => 92u32,
896             };
897         }
898         "#,
899         expect![[r#"
900             51..110 '{     ...  }; }': ()
901             61..62 'x': u32
902             65..107 'match ...     }': u32
903             71..73 '()': ()
904             84..91 'unit!()': ()
905             95..100 '92u32': u32
906         "#]],
907     );
908 }