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