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