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