]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/macros.rs
Move to upstream `macro_rules!` model
[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 #[ignore]
544 fn include_accidentally_quadratic() {
545     let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic");
546     let big_file = fs::read_to_string(file).unwrap();
547     let big_file = vec![big_file; 10].join("\n");
548
549     let fixture = r#"
550 //- /main.rs
551 #[rustc_builtin_macro]
552 macro_rules! include {() => {}}
553
554 include!("foo.rs");
555
556 fn main() {
557     RegisterBlock { };
558                   //^ RegisterBlock
559 }
560     "#;
561     let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file);
562     check_types(&fixture);
563 }
564
565 #[test]
566 fn infer_builtin_macros_include_concat() {
567     check_types(
568         r#"
569 //- /main.rs
570 #[rustc_builtin_macro]
571 macro_rules! include {() => {}}
572
573 #[rustc_builtin_macro]
574 macro_rules! concat {() => {}}
575
576 include!(concat!("f", "oo.rs"));
577
578 fn main() {
579     bar();
580 }     //^ u32
581
582 //- /foo.rs
583 fn bar() -> u32 {0}
584 "#,
585     );
586 }
587
588 #[test]
589 fn infer_builtin_macros_include_concat_with_bad_env_should_failed() {
590     check_types(
591         r#"
592 //- /main.rs
593 #[rustc_builtin_macro]
594 macro_rules! include {() => {}}
595
596 #[rustc_builtin_macro]
597 macro_rules! concat {() => {}}
598
599 #[rustc_builtin_macro]
600 macro_rules! env {() => {}}
601
602 include!(concat!(env!("OUT_DIR"), "/foo.rs"));
603
604 fn main() {
605     bar();
606 }     //^ {unknown}
607
608 //- /foo.rs
609 fn bar() -> u32 {0}
610 "#,
611     );
612 }
613
614 #[test]
615 fn infer_builtin_macros_include_itself_should_failed() {
616     check_types(
617         r#"
618 #[rustc_builtin_macro]
619 macro_rules! include {() => {}}
620
621 include!("main.rs");
622
623 fn main() {
624             0
625 } //^ i32
626 "#,
627     );
628 }
629
630 #[test]
631 fn infer_builtin_macros_concat_with_lazy() {
632     check_infer(
633         r#"
634         macro_rules! hello {() => {"hello"}}
635
636         #[rustc_builtin_macro]
637         macro_rules! concat {() => {}}
638
639         fn main() {
640             let x = concat!(hello!(), concat!("world", "!"));
641         }
642         "#,
643         expect![[r#"
644             !0..13 '"helloworld!"': &str
645             103..160 '{     ...")); }': ()
646             113..114 'x': &str
647         "#]],
648     );
649 }
650
651 #[test]
652 fn infer_builtin_macros_env() {
653     check_infer(
654         r#"
655         //- /main.rs env:foo=bar
656         #[rustc_builtin_macro]
657         macro_rules! env {() => {}}
658
659         fn main() {
660             let x = env!("foo");
661         }
662         "#,
663         expect![[r#"
664             !0..22 '"__RA_...TED__"': &str
665             62..90 '{     ...o"); }': ()
666             72..73 'x': &str
667         "#]],
668     );
669 }
670
671 #[test]
672 fn infer_derive_clone_simple() {
673     check_types(
674         r#"
675 //- /main.rs crate:main deps:core
676 #[derive(Clone)]
677 struct S;
678 fn test() {
679     S.clone();
680 }         //^ S
681
682 //- /lib.rs crate:core
683 #[prelude_import]
684 use clone::*;
685 mod clone {
686     trait Clone {
687         fn clone(&self) -> Self;
688     }
689 }
690 "#,
691     );
692 }
693
694 #[test]
695 fn infer_derive_clone_in_core() {
696     check_types(
697         r#"
698 //- /lib.rs crate:core
699 #[prelude_import]
700 use clone::*;
701 mod clone {
702     trait Clone {
703         fn clone(&self) -> Self;
704     }
705 }
706 #[derive(Clone)]
707 pub struct S;
708
709 //- /main.rs crate:main deps:core
710 use core::S;
711 fn test() {
712     S.clone();
713 }         //^ S
714 "#,
715     );
716 }
717
718 #[test]
719 fn infer_derive_clone_with_params() {
720     check_types(
721         r#"
722 //- /main.rs crate:main deps:core
723 #[derive(Clone)]
724 struct S;
725 #[derive(Clone)]
726 struct Wrapper<T>(T);
727 struct NonClone;
728 fn test() {
729     (Wrapper(S).clone(), Wrapper(NonClone).clone());
730   //^ (Wrapper<S>, {unknown})
731 }
732
733 //- /lib.rs crate:core
734 #[prelude_import]
735 use clone::*;
736 mod clone {
737     trait Clone {
738         fn clone(&self) -> Self;
739     }
740 }
741 "#,
742     );
743 }
744
745 #[test]
746 fn infer_custom_derive_simple() {
747     // FIXME: this test current now do nothing
748     check_types(
749         r#"
750 //- /main.rs crate:main
751 use foo::Foo;
752
753 #[derive(Foo)]
754 struct S{}
755
756 fn test() {
757     S{};
758 }   //^ S
759 "#,
760     );
761 }
762
763 #[test]
764 fn macro_in_arm() {
765     check_infer(
766         r#"
767         macro_rules! unit {
768             () => { () };
769         }
770
771         fn main() {
772             let x = match () {
773                 unit!() => 92u32,
774             };
775         }
776         "#,
777         expect![[r#"
778             51..110 '{     ...  }; }': ()
779             61..62 'x': u32
780             65..107 'match ...     }': u32
781             71..73 '()': ()
782             84..91 'unit!()': ()
783             95..100 '92u32': u32
784         "#]],
785     );
786 }