]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/macros.rs
Merge #7110
[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_macro_with_dollar_crate_in_def_site() {
375     check_types(
376         r#"
377 //- /main.rs crate:main deps:foo
378 use foo::expand;
379
380 macro_rules! list {
381     ($($tt:tt)*) => { $($tt)* }
382 }
383
384 fn test() {
385     let r = expand!();
386     r;
387   //^ u128
388 }
389
390 //- /lib.rs crate:foo
391 #[macro_export]
392 macro_rules! expand {
393     () => { list!($crate::m!()) };
394 }
395
396 #[macro_export]
397 macro_rules! m {
398     () => { 0u128 };
399 }
400 "#,
401     );
402 }
403
404 #[test]
405 fn infer_type_value_non_legacy_macro_use_as() {
406     check_infer(
407         r#"
408         mod m {
409             macro_rules! _foo {
410                 ($x:ident) => { type $x = u64; }
411             }
412             pub(crate) use _foo as foo;
413         }
414
415         m::foo!(foo);
416         use foo as bar;
417         fn f() -> bar { 0 }
418         fn main() {
419             let _a  = f();
420         }
421         "#,
422         expect![[r#"
423             158..163 '{ 0 }': u64
424             160..161 '0': u64
425             174..196 '{     ...f(); }': ()
426             184..186 '_a': u64
427             190..191 'f': fn f() -> u64
428             190..193 'f()': u64
429         "#]],
430     );
431 }
432
433 #[test]
434 fn infer_local_macro() {
435     check_infer(
436         r#"
437         fn main() {
438             macro_rules! foo {
439                 () => { 1usize }
440             }
441             let _a  = foo!();
442         }
443         "#,
444         expect![[r#"
445             !0..6 '1usize': usize
446             10..89 '{     ...!(); }': ()
447             74..76 '_a': usize
448         "#]],
449     );
450 }
451
452 #[test]
453 fn infer_local_inner_macros() {
454     check_types(
455         r#"
456 //- /main.rs crate:main deps:foo
457 fn test() {
458     let x = foo::foo!(1);
459     x;
460 } //^ i32
461
462 //- /lib.rs crate:foo
463 #[macro_export(local_inner_macros)]
464 macro_rules! foo {
465     (1) => { bar!() };
466 }
467
468 #[macro_export]
469 macro_rules! bar {
470     () => { 42 }
471 }
472
473 "#,
474     );
475 }
476
477 #[test]
478 fn infer_builtin_macros_line() {
479     check_infer(
480         r#"
481         #[rustc_builtin_macro]
482         macro_rules! line {() => {}}
483
484         fn main() {
485             let x = line!();
486         }
487         "#,
488         expect![[r#"
489             !0..1 '0': i32
490             63..87 '{     ...!(); }': ()
491             73..74 'x': i32
492         "#]],
493     );
494 }
495
496 #[test]
497 fn infer_builtin_macros_file() {
498     check_infer(
499         r#"
500         #[rustc_builtin_macro]
501         macro_rules! file {() => {}}
502
503         fn main() {
504             let x = file!();
505         }
506         "#,
507         expect![[r#"
508             !0..2 '""': &str
509             63..87 '{     ...!(); }': ()
510             73..74 'x': &str
511         "#]],
512     );
513 }
514
515 #[test]
516 fn infer_builtin_macros_column() {
517     check_infer(
518         r#"
519         #[rustc_builtin_macro]
520         macro_rules! column {() => {}}
521
522         fn main() {
523             let x = column!();
524         }
525         "#,
526         expect![[r#"
527             !0..1 '0': i32
528             65..91 '{     ...!(); }': ()
529             75..76 'x': i32
530         "#]],
531     );
532 }
533
534 #[test]
535 fn infer_builtin_macros_concat() {
536     check_infer(
537         r#"
538         #[rustc_builtin_macro]
539         macro_rules! concat {() => {}}
540
541         fn main() {
542             let x = concat!("hello", concat!("world", "!"));
543         }
544         "#,
545         expect![[r#"
546             !0..13 '"helloworld!"': &str
547             65..121 '{     ...")); }': ()
548             75..76 'x': &str
549         "#]],
550     );
551 }
552
553 #[test]
554 fn infer_builtin_macros_include() {
555     check_types(
556         r#"
557 //- /main.rs
558 #[rustc_builtin_macro]
559 macro_rules! include {() => {}}
560
561 include!("foo.rs");
562
563 fn main() {
564     bar();
565 }     //^ u32
566
567 //- /foo.rs
568 fn bar() -> u32 {0}
569 "#,
570     );
571 }
572
573 #[test]
574 fn infer_builtin_macros_include_str() {
575     check_types(
576         r#"
577 //- /main.rs
578 #[rustc_builtin_macro]
579 macro_rules! include_str {() => {}}
580
581 fn main() {
582     let a = include_str!("foo.rs");
583     a;
584 } //^ &str
585
586 //- /foo.rs
587 hello
588 "#,
589     );
590 }
591
592 #[test]
593 fn infer_builtin_macros_include_str_with_lazy_nested() {
594     check_types(
595         r#"
596 //- /main.rs
597 #[rustc_builtin_macro]
598 macro_rules! concat {() => {}}
599 #[rustc_builtin_macro]
600 macro_rules! include_str {() => {}}
601
602 macro_rules! m {
603     ($x:expr) => {
604         concat!("foo", $x)
605     };
606 }
607
608 fn main() {
609     let a = include_str!(m!(".rs"));
610     a;
611 } //^ &str
612
613 //- /foo.rs
614 hello
615 "#,
616     );
617 }
618
619 #[test]
620 #[ignore]
621 fn include_accidentally_quadratic() {
622     let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic");
623     let big_file = fs::read_to_string(file).unwrap();
624     let big_file = vec![big_file; 10].join("\n");
625
626     let fixture = r#"
627 //- /main.rs
628 #[rustc_builtin_macro]
629 macro_rules! include {() => {}}
630
631 include!("foo.rs");
632
633 fn main() {
634     RegisterBlock { };
635                   //^ RegisterBlock
636 }
637     "#;
638     let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file);
639     check_types(&fixture);
640 }
641
642 #[test]
643 fn infer_builtin_macros_include_concat() {
644     check_types(
645         r#"
646 //- /main.rs
647 #[rustc_builtin_macro]
648 macro_rules! include {() => {}}
649
650 #[rustc_builtin_macro]
651 macro_rules! concat {() => {}}
652
653 include!(concat!("f", "oo.rs"));
654
655 fn main() {
656     bar();
657 }     //^ u32
658
659 //- /foo.rs
660 fn bar() -> u32 {0}
661 "#,
662     );
663 }
664
665 #[test]
666 fn infer_builtin_macros_include_concat_with_bad_env_should_failed() {
667     check_types(
668         r#"
669 //- /main.rs
670 #[rustc_builtin_macro]
671 macro_rules! include {() => {}}
672
673 #[rustc_builtin_macro]
674 macro_rules! concat {() => {}}
675
676 #[rustc_builtin_macro]
677 macro_rules! env {() => {}}
678
679 include!(concat!(env!("OUT_DIR"), "/foo.rs"));
680
681 fn main() {
682     bar();
683 }     //^ {unknown}
684
685 //- /foo.rs
686 fn bar() -> u32 {0}
687 "#,
688     );
689 }
690
691 #[test]
692 fn infer_builtin_macros_include_itself_should_failed() {
693     check_types(
694         r#"
695 #[rustc_builtin_macro]
696 macro_rules! include {() => {}}
697
698 include!("main.rs");
699
700 fn main() {
701             0
702 } //^ i32
703 "#,
704     );
705 }
706
707 #[test]
708 fn infer_builtin_macros_concat_with_lazy() {
709     check_infer(
710         r#"
711         macro_rules! hello {() => {"hello"}}
712
713         #[rustc_builtin_macro]
714         macro_rules! concat {() => {}}
715
716         fn main() {
717             let x = concat!(hello!(), concat!("world", "!"));
718         }
719         "#,
720         expect![[r#"
721             !0..13 '"helloworld!"': &str
722             103..160 '{     ...")); }': ()
723             113..114 'x': &str
724         "#]],
725     );
726 }
727
728 #[test]
729 fn infer_builtin_macros_env() {
730     check_infer(
731         r#"
732         //- /main.rs env:foo=bar
733         #[rustc_builtin_macro]
734         macro_rules! env {() => {}}
735
736         fn main() {
737             let x = env!("foo");
738         }
739         "#,
740         expect![[r#"
741             !0..22 '"__RA_...TED__"': &str
742             62..90 '{     ...o"); }': ()
743             72..73 'x': &str
744         "#]],
745     );
746 }
747
748 #[test]
749 fn infer_derive_clone_simple() {
750     check_types(
751         r#"
752 //- /main.rs crate:main deps:core
753 #[derive(Clone)]
754 struct S;
755 fn test() {
756     S.clone();
757 }         //^ S
758
759 //- /lib.rs crate:core
760 #[prelude_import]
761 use clone::*;
762 mod clone {
763     trait Clone {
764         fn clone(&self) -> Self;
765     }
766     #[rustc_builtin_macro]
767     macro Clone {}
768 }
769 "#,
770     );
771 }
772
773 #[test]
774 fn infer_derive_clone_in_core() {
775     check_types(
776         r#"
777 //- /lib.rs crate:core
778 #[prelude_import]
779 use clone::*;
780 mod clone {
781     trait Clone {
782         fn clone(&self) -> Self;
783     }
784     #[rustc_builtin_macro]
785     macro Clone {}
786 }
787 #[derive(Clone)]
788 pub struct S;
789
790 //- /main.rs crate:main deps:core
791 use core::S;
792 fn test() {
793     S.clone();
794 }         //^ S
795 "#,
796     );
797 }
798
799 #[test]
800 fn infer_derive_clone_with_params() {
801     check_types(
802         r#"
803 //- /main.rs crate:main deps:core
804 #[derive(Clone)]
805 struct S;
806 #[derive(Clone)]
807 struct Wrapper<T>(T);
808 struct NonClone;
809 fn test() {
810     (Wrapper(S).clone(), Wrapper(NonClone).clone());
811   //^ (Wrapper<S>, {unknown})
812 }
813
814 //- /lib.rs crate:core
815 #[prelude_import]
816 use clone::*;
817 mod clone {
818     trait Clone {
819         fn clone(&self) -> Self;
820     }
821     #[rustc_builtin_macro]
822     macro Clone {}
823 }
824 "#,
825     );
826 }
827
828 #[test]
829 fn infer_custom_derive_simple() {
830     // FIXME: this test current now do nothing
831     check_types(
832         r#"
833 //- /main.rs crate:main
834 use foo::Foo;
835
836 #[derive(Foo)]
837 struct S{}
838
839 fn test() {
840     S{};
841 }   //^ S
842 "#,
843     );
844 }
845
846 #[test]
847 fn macro_in_arm() {
848     check_infer(
849         r#"
850         macro_rules! unit {
851             () => { () };
852         }
853
854         fn main() {
855             let x = match () {
856                 unit!() => 92u32,
857             };
858         }
859         "#,
860         expect![[r#"
861             51..110 '{     ...  }; }': ()
862             61..62 'x': u32
863             65..107 'match ...     }': u32
864             71..73 '()': ()
865             84..91 'unit!()': ()
866             95..100 '92u32': u32
867         "#]],
868     );
869 }