]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/nameres/tests/macros.rs
Refactor name resolution to resolve derive helpers
[rust.git] / crates / hir_def / src / nameres / tests / macros.rs
1 use super::*;
2 use crate::nameres::proc_macro::{ProcMacroDef, ProcMacroKind};
3
4 #[test]
5 fn macro_rules_are_globally_visible() {
6     check(
7         r#"
8 //- /lib.rs
9 macro_rules! structs {
10     ($($i:ident),*) => {
11         $(struct $i { field: u32 } )*
12     }
13 }
14 structs!(Foo);
15 mod nested;
16
17 //- /nested.rs
18 structs!(Bar, Baz);
19 "#,
20         expect![[r#"
21             crate
22             Foo: t
23             nested: t
24
25             crate::nested
26             Bar: t
27             Baz: t
28         "#]],
29     );
30 }
31
32 #[test]
33 fn macro_rules_can_define_modules() {
34     check(
35         r#"
36 //- /lib.rs
37 macro_rules! m {
38     ($name:ident) => { mod $name;  }
39 }
40 m!(n1);
41 mod m { m!(n3) }
42
43 //- /n1.rs
44 m!(n2)
45 //- /n1/n2.rs
46 struct X;
47 //- /m/n3.rs
48 struct Y;
49 "#,
50         expect![[r#"
51             crate
52             m: t
53             n1: t
54
55             crate::m
56             n3: t
57
58             crate::m::n3
59             Y: t v
60
61             crate::n1
62             n2: t
63
64             crate::n1::n2
65             X: t v
66         "#]],
67     );
68 }
69
70 #[test]
71 fn macro_rules_from_other_crates_are_visible() {
72     check(
73         r#"
74 //- /main.rs crate:main deps:foo
75 foo::structs!(Foo, Bar)
76 mod bar;
77
78 //- /bar.rs
79 use crate::*;
80
81 //- /lib.rs crate:foo
82 #[macro_export]
83 macro_rules! structs {
84     ($($i:ident),*) => {
85         $(struct $i { field: u32 } )*
86     }
87 }
88 "#,
89         expect![[r#"
90             crate
91             Bar: t
92             Foo: t
93             bar: t
94
95             crate::bar
96             Bar: t
97             Foo: t
98             bar: t
99         "#]],
100     );
101 }
102
103 #[test]
104 fn macro_rules_export_with_local_inner_macros_are_visible() {
105     check(
106         r#"
107 //- /main.rs crate:main deps:foo
108 foo::structs!(Foo, Bar)
109 mod bar;
110
111 //- /bar.rs
112 use crate::*;
113
114 //- /lib.rs crate:foo
115 #[macro_export(local_inner_macros)]
116 macro_rules! structs {
117     ($($i:ident),*) => {
118         $(struct $i { field: u32 } )*
119     }
120 }
121 "#,
122         expect![[r#"
123             crate
124             Bar: t
125             Foo: t
126             bar: t
127
128             crate::bar
129             Bar: t
130             Foo: t
131             bar: t
132         "#]],
133     );
134 }
135
136 #[test]
137 fn local_inner_macros_makes_local_macros_usable() {
138     check(
139         r#"
140 //- /main.rs crate:main deps:foo
141 foo::structs!(Foo, Bar);
142 mod bar;
143
144 //- /bar.rs
145 use crate::*;
146
147 //- /lib.rs crate:foo
148 #[macro_export(local_inner_macros)]
149 macro_rules! structs {
150     ($($i:ident),*) => {
151         inner!($($i),*);
152     }
153 }
154 #[macro_export]
155 macro_rules! inner {
156     ($($i:ident),*) => {
157         $(struct $i { field: u32 } )*
158     }
159 }
160 "#,
161         expect![[r#"
162             crate
163             Bar: t
164             Foo: t
165             bar: t
166
167             crate::bar
168             Bar: t
169             Foo: t
170             bar: t
171         "#]],
172     );
173 }
174
175 #[test]
176 fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
177     check(
178         r#"
179 //- /main.rs crate:main deps:foo
180 macro_rules! baz {
181     () => {
182         use foo::bar;
183     }
184 }
185 foo!();
186 bar!();
187 baz!();
188
189 //- /lib.rs crate:foo
190 #[macro_export]
191 macro_rules! foo {
192     () => {
193         struct Foo { field: u32 }
194     }
195 }
196 #[macro_export]
197 macro_rules! bar {
198     () => {
199         use foo::foo;
200     }
201 }
202 "#,
203         expect![[r#"
204             crate
205             Foo: t
206             bar: m
207             foo: m
208         "#]],
209     );
210 }
211
212 #[test]
213 fn macro_rules_from_other_crates_are_visible_with_macro_use() {
214     cov_mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
215     check(
216         r#"
217 //- /main.rs crate:main deps:foo
218 structs!(Foo);
219 structs_priv!(Bar);
220 structs_not_exported!(MacroNotResolved1);
221 crate::structs!(MacroNotResolved2);
222
223 mod bar;
224
225 #[macro_use]
226 extern crate foo;
227
228 //- /bar.rs
229 structs!(Baz);
230 crate::structs!(MacroNotResolved3);
231
232 //- /lib.rs crate:foo
233 #[macro_export]
234 macro_rules! structs {
235     ($i:ident) => { struct $i; }
236 }
237
238 macro_rules! structs_not_exported {
239     ($i:ident) => { struct $i; }
240 }
241
242 mod priv_mod {
243     #[macro_export]
244     macro_rules! structs_priv {
245         ($i:ident) => { struct $i; }
246     }
247 }
248 "#,
249         expect![[r#"
250             crate
251             Bar: t v
252             Foo: t v
253             bar: t
254             foo: t
255
256             crate::bar
257             Baz: t v
258         "#]],
259     );
260 }
261
262 #[test]
263 fn prelude_is_macro_use() {
264     cov_mark::check!(prelude_is_macro_use);
265     check(
266         r#"
267 //- /main.rs crate:main deps:foo
268 structs!(Foo);
269 structs_priv!(Bar);
270 structs_outside!(Out);
271 crate::structs!(MacroNotResolved2);
272
273 mod bar;
274
275 //- /bar.rs
276 structs!(Baz);
277 crate::structs!(MacroNotResolved3);
278
279 //- /lib.rs crate:foo
280 #[prelude_import]
281 use self::prelude::*;
282
283 mod prelude {
284     #[macro_export]
285     macro_rules! structs {
286         ($i:ident) => { struct $i; }
287     }
288
289     mod priv_mod {
290         #[macro_export]
291         macro_rules! structs_priv {
292             ($i:ident) => { struct $i; }
293         }
294     }
295 }
296
297 #[macro_export]
298 macro_rules! structs_outside {
299     ($i:ident) => { struct $i; }
300 }
301 "#,
302         expect![[r#"
303             crate
304             Bar: t v
305             Foo: t v
306             Out: t v
307             bar: t
308
309             crate::bar
310             Baz: t v
311         "#]],
312     );
313 }
314
315 #[test]
316 fn prelude_cycle() {
317     check(
318         r#"
319 #[prelude_import]
320 use self::prelude::*;
321
322 declare_mod!();
323
324 mod prelude {
325     macro_rules! declare_mod {
326         () => (mod foo {})
327     }
328 }
329 "#,
330         expect![[r#"
331             crate
332             prelude: t
333
334             crate::prelude
335         "#]],
336     );
337 }
338
339 #[test]
340 fn plain_macros_are_legacy_textual_scoped() {
341     check(
342         r#"
343 //- /main.rs
344 mod m1;
345 bar!(NotFoundNotMacroUse);
346
347 mod m2 { foo!(NotFoundBeforeInside2); }
348
349 macro_rules! foo {
350     ($x:ident) => { struct $x; }
351 }
352 foo!(Ok);
353
354 mod m3;
355 foo!(OkShadowStop);
356 bar!(NotFoundMacroUseStop);
357
358 #[macro_use]
359 mod m5 {
360     #[macro_use]
361     mod m6 {
362         macro_rules! foo {
363             ($x:ident) => { fn $x() {} }
364         }
365     }
366 }
367 foo!(ok_double_macro_use_shadow);
368
369 baz!(NotFoundBefore);
370 #[macro_use]
371 mod m7 {
372     macro_rules! baz {
373         ($x:ident) => { struct $x; }
374     }
375 }
376 baz!(OkAfter);
377
378 //- /m1.rs
379 foo!(NotFoundBeforeInside1);
380 macro_rules! bar {
381     ($x:ident) => { struct $x; }
382 }
383
384 //- /m3/mod.rs
385 foo!(OkAfterInside);
386 macro_rules! foo {
387     ($x:ident) => { fn $x() {} }
388 }
389 foo!(ok_shadow);
390
391 #[macro_use]
392 mod m4;
393 bar!(OkMacroUse);
394
395 mod m5;
396 baz!(OkMacroUseInner);
397
398 //- /m3/m4.rs
399 foo!(ok_shadow_deep);
400 macro_rules! bar {
401     ($x:ident) => { struct $x; }
402 }
403 //- /m3/m5.rs
404 #![macro_use]
405 macro_rules! baz {
406     ($x:ident) => { struct $x; }
407 }
408
409
410 "#,
411         expect![[r#"
412             crate
413             Ok: t v
414             OkAfter: t v
415             OkShadowStop: t v
416             m1: t
417             m2: t
418             m3: t
419             m5: t
420             m7: t
421             ok_double_macro_use_shadow: v
422
423             crate::m7
424
425             crate::m1
426
427             crate::m5
428             m6: t
429
430             crate::m5::m6
431
432             crate::m2
433
434             crate::m3
435             OkAfterInside: t v
436             OkMacroUse: t v
437             OkMacroUseInner: t v
438             m4: t
439             m5: t
440             ok_shadow: v
441
442             crate::m3::m4
443             ok_shadow_deep: v
444
445             crate::m3::m5
446         "#]],
447     );
448 }
449
450 #[test]
451 fn type_value_macro_live_in_different_scopes() {
452     check(
453         r#"
454 #[macro_export]
455 macro_rules! foo {
456     ($x:ident) => { type $x = (); }
457 }
458
459 foo!(foo);
460 use foo as bar;
461
462 use self::foo as baz;
463 fn baz() {}
464 "#,
465         expect![[r#"
466             crate
467             bar: t m
468             baz: t v m
469             foo: t m
470         "#]],
471     );
472 }
473
474 #[test]
475 fn macro_use_can_be_aliased() {
476     check(
477         r#"
478 //- /main.rs crate:main deps:foo
479 #[macro_use]
480 extern crate foo;
481
482 foo!(Direct);
483 bar!(Alias);
484
485 //- /lib.rs crate:foo
486 use crate::foo as bar;
487
488 mod m {
489     #[macro_export]
490     macro_rules! foo {
491         ($x:ident) => { struct $x; }
492     }
493 }
494 "#,
495         expect![[r#"
496             crate
497             Alias: t v
498             Direct: t v
499             foo: t
500         "#]],
501     );
502 }
503
504 #[test]
505 fn path_qualified_macros() {
506     check(
507         r#"
508 macro_rules! foo {
509     ($x:ident) => { struct $x; }
510 }
511
512 crate::foo!(NotResolved);
513
514 crate::bar!(OkCrate);
515 bar!(OkPlain);
516 alias1!(NotHere);
517 m::alias1!(OkAliasPlain);
518 m::alias2!(OkAliasSuper);
519 m::alias3!(OkAliasCrate);
520 not_found!(NotFound);
521
522 mod m {
523     #[macro_export]
524     macro_rules! bar {
525         ($x:ident) => { struct $x; }
526     }
527     pub use bar as alias1;
528     pub use super::bar as alias2;
529     pub use crate::bar as alias3;
530     pub use self::bar as not_found;
531 }
532 "#,
533         expect![[r#"
534             crate
535             OkAliasCrate: t v
536             OkAliasPlain: t v
537             OkAliasSuper: t v
538             OkCrate: t v
539             OkPlain: t v
540             bar: m
541             m: t
542
543             crate::m
544             alias1: m
545             alias2: m
546             alias3: m
547             not_found: _
548         "#]],
549     );
550 }
551
552 #[test]
553 fn macro_dollar_crate_is_correct_in_item() {
554     cov_mark::check!(macro_dollar_crate_self);
555     check(
556         r#"
557 //- /main.rs crate:main deps:foo
558 #[macro_use]
559 extern crate foo;
560
561 #[macro_use]
562 mod m {
563     macro_rules! current {
564         () => {
565             use $crate::Foo as FooSelf;
566         }
567     }
568 }
569
570 struct Foo;
571
572 current!();
573 not_current1!();
574 foo::not_current2!();
575
576 //- /lib.rs crate:foo
577 mod m {
578     #[macro_export]
579     macro_rules! not_current1 {
580         () => {
581             use $crate::Bar;
582         }
583     }
584 }
585
586 #[macro_export]
587 macro_rules! not_current2 {
588     () => {
589         use $crate::Baz;
590     }
591 }
592
593 struct Bar;
594 struct Baz;
595 "#,
596         expect![[r#"
597             crate
598             Bar: t v
599             Baz: t v
600             Foo: t v
601             FooSelf: t v
602             foo: t
603             m: t
604
605             crate::m
606         "#]],
607     );
608 }
609
610 #[test]
611 fn macro_dollar_crate_is_correct_in_indirect_deps() {
612     cov_mark::check!(macro_dollar_crate_other);
613     // From std
614     check(
615         r#"
616 //- /main.rs crate:main deps:std
617 foo!();
618
619 //- /std.rs crate:std deps:core
620 #[prelude_import]
621 use self::prelude::*;
622
623 pub use core::foo;
624
625 mod prelude {}
626
627 #[macro_use]
628 mod std_macros;
629
630 //- /core.rs crate:core
631 #[macro_export]
632 macro_rules! foo {
633     () => {
634         use $crate::bar;
635     }
636 }
637
638 pub struct bar;
639 "#,
640         expect![[r#"
641             crate
642             bar: t v
643         "#]],
644     );
645 }
646
647 #[test]
648 fn expand_derive() {
649     let map = compute_crate_def_map(
650         r#"
651         //- /main.rs crate:main deps:core
652         use core::Copy;
653
654         #[derive(Copy, core::Clone)]
655         struct Foo;
656
657         //- /core.rs crate:core
658         #[rustc_builtin_macro]
659         pub macro Copy {}
660
661         #[rustc_builtin_macro]
662         pub macro Clone {}
663         "#,
664     );
665     assert_eq!(map.modules[map.root].scope.impls().len(), 2);
666 }
667
668 #[test]
669 fn resolve_builtin_derive() {
670     check(
671         r#"
672 //- /main.rs crate:main deps:core
673 use core::*;
674
675 //- /core.rs crate:core
676 #[rustc_builtin_macro]
677 pub macro Clone {}
678
679 pub trait Clone {}
680 "#,
681         expect![[r#"
682             crate
683             Clone: t m
684         "#]],
685     );
686 }
687
688 #[test]
689 fn builtin_derive_with_unresolved_attributes_fall_back() {
690     // Tests that we still resolve derives after ignoring an unresolved attribute.
691     cov_mark::check!(unresolved_attribute_fallback);
692     let map = compute_crate_def_map(
693         r#"
694         //- /main.rs crate:main deps:core
695         use core::Clone;
696
697         #[derive(Clone)]
698         #[unresolved]
699         struct Foo;
700
701         //- /core.rs crate:core
702         #[rustc_builtin_macro]
703         pub macro Clone {}
704         "#,
705     );
706     assert_eq!(map.modules[map.root].scope.impls().len(), 1);
707 }
708
709 #[test]
710 fn unresolved_attributes_fall_back_track_per_file_moditems() {
711     // Tests that we track per-file ModItems when ignoring an unresolved attribute.
712     // Just tracking the `ModItem` leads to `Foo` getting ignored.
713
714     check(
715         r#"
716         //- /main.rs crate:main
717
718         mod submod;
719
720         #[unresolved]
721         struct Foo;
722
723         //- /submod.rs
724         #[unresolved]
725         struct Bar;
726         "#,
727         expect![[r#"
728             crate
729             Foo: t v
730             submod: t
731
732             crate::submod
733             Bar: t v
734         "#]],
735     );
736 }
737
738 #[test]
739 fn resolves_derive_helper() {
740     cov_mark::check!(resolved_derive_helper);
741     check(
742         r#"
743 //- /main.rs crate:main deps:proc
744 #[derive(proc::Derive)]
745 #[helper]
746 #[unresolved]
747 struct S;
748
749 //- /proc.rs crate:proc
750 #[proc_macro_derive(Derive, attributes(helper))]
751 fn derive() {}
752         "#,
753         expect![[r#"
754             crate
755             S: t v
756         "#]],
757     )
758 }
759
760 #[test]
761 fn macro_expansion_overflow() {
762     cov_mark::check!(macro_expansion_overflow);
763     check(
764         r#"
765 macro_rules! a {
766     ($e:expr; $($t:tt)*) => {
767         b!(static = (); $($t)*);
768     };
769     () => {};
770 }
771
772 macro_rules! b {
773     (static = $e:expr; $($t:tt)*) => {
774         a!($e; $($t)*);
775     };
776     () => {};
777 }
778
779 b! { static = #[] ();}
780 "#,
781         expect![[r#"
782             crate
783         "#]],
784     );
785 }
786
787 #[test]
788 fn macros_defining_macros() {
789     check(
790         r#"
791 macro_rules! item {
792     ($item:item) => { $item }
793 }
794
795 item! {
796     macro_rules! indirect_macro { () => { struct S {} } }
797 }
798
799 indirect_macro!();
800     "#,
801         expect![[r#"
802             crate
803             S: t
804         "#]],
805     );
806 }
807
808 #[test]
809 fn resolves_proc_macros() {
810     check(
811         r"
812         struct TokenStream;
813
814         #[proc_macro]
815         pub fn function_like_macro(args: TokenStream) -> TokenStream {
816             args
817         }
818
819         #[proc_macro_attribute]
820         pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
821             item
822         }
823
824         #[proc_macro_derive(DummyTrait)]
825         pub fn derive_macro(_item: TokenStream) -> TokenStream {
826             TokenStream
827         }
828
829         #[proc_macro_derive(AnotherTrait, attributes(helper_attr))]
830         pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
831             TokenStream
832         }
833         ",
834         expect![[r#"
835             crate
836             AnotherTrait: m
837             DummyTrait: m
838             TokenStream: t v
839             attribute_macro: v m
840             derive_macro: v
841             derive_macro_2: v
842             function_like_macro: v m
843         "#]],
844     );
845 }
846
847 #[test]
848 fn proc_macro_censoring() {
849     // Make sure that only proc macros are publicly exported from proc-macro crates.
850
851     check(
852         r"
853         //- /main.rs crate:main deps:macros
854         pub use macros::*;
855
856         //- /macros.rs crate:macros
857         pub struct TokenStream;
858
859         #[proc_macro]
860         pub fn function_like_macro(args: TokenStream) -> TokenStream {
861             args
862         }
863
864         #[proc_macro_attribute]
865         pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
866             item
867         }
868
869         #[proc_macro_derive(DummyTrait)]
870         pub fn derive_macro(_item: TokenStream) -> TokenStream {
871             TokenStream
872         }
873
874         #[macro_export]
875         macro_rules! mbe {
876             () => {};
877         }
878         ",
879         expect![[r#"
880             crate
881             DummyTrait: m
882             attribute_macro: m
883             function_like_macro: m
884         "#]],
885     );
886 }
887
888 #[test]
889 fn collects_derive_helpers() {
890     let def_map = compute_crate_def_map(
891         r"
892         struct TokenStream;
893
894         #[proc_macro_derive(AnotherTrait, attributes(helper_attr))]
895         pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
896             TokenStream
897         }
898         ",
899     );
900
901     assert_eq!(def_map.exported_proc_macros.len(), 1);
902     match def_map.exported_proc_macros.values().next() {
903         Some(ProcMacroDef { kind: ProcMacroKind::CustomDerive { helpers }, .. }) => {
904             match &**helpers {
905                 [attr] => assert_eq!(attr.to_string(), "helper_attr"),
906                 _ => unreachable!(),
907             }
908         }
909         _ => unreachable!(),
910     }
911 }
912
913 #[test]
914 fn resolve_macro_def() {
915     check(
916         r#"
917 pub macro structs($($i:ident),*) {
918     $(struct $i { field: u32 } )*
919 }
920 structs!(Foo);
921 "#,
922         expect![[r#"
923             crate
924             Foo: t
925             structs: m
926         "#]],
927     );
928 }