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