1 use super::*;
2 use itertools::Itertools;
3
4 #[test]
macro_rules_are_globally_visible()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]
macro_rules_can_define_modules()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]
macro_rules_from_other_crates_are_visible()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]
macro_rules_export_with_local_inner_macros_are_visible()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]
local_inner_macros_makes_local_macros_usable()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]
unexpanded_macro_should_expand_by_fixedpoint_loop()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]
macro_rules_from_other_crates_are_visible_with_macro_use()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]
macro_use_filter()263 fn macro_use_filter() {
264 check(
265 r#"
266 //- /main.rs crate:main deps:empty,multiple,all
267 #[macro_use()]
268 extern crate empty;
269
270 foo_not_imported!();
271
272 #[macro_use(bar1)]
273 #[macro_use()]
274 #[macro_use(bar2, bar3)]
275 extern crate multiple;
276
277 bar1!();
278 bar2!();
279 bar3!();
280 bar_not_imported!();
281
282 #[macro_use(baz1)]
283 #[macro_use]
284 #[macro_use(baz2)]
285 extern crate all;
286
287 baz1!();
288 baz2!();
289 baz3!();
290
291 //- /empty.rs crate:empty
292 #[macro_export]
293 macro_rules! foo_not_imported { () => { struct NotOkFoo; } }
294
295 //- /multiple.rs crate:multiple
296 #[macro_export]
297 macro_rules! bar1 { () => { struct OkBar1; } }
298 #[macro_export]
299 macro_rules! bar2 { () => { struct OkBar2; } }
300 #[macro_export]
301 macro_rules! bar3 { () => { struct OkBar3; } }
302 #[macro_export]
303 macro_rules! bar_not_imported { () => { struct NotOkBar; } }
304
305 //- /all.rs crate:all
306 #[macro_export]
307 macro_rules! baz1 { () => { struct OkBaz1; } }
308 #[macro_export]
309 macro_rules! baz2 { () => { struct OkBaz2; } }
310 #[macro_export]
311 macro_rules! baz3 { () => { struct OkBaz3; } }
312 "#,
313 expect![[r#"
314 crate
315 OkBar1: t v
316 OkBar2: t v
317 OkBar3: t v
318 OkBaz1: t v
319 OkBaz2: t v
320 OkBaz3: t v
321 all: t
322 empty: t
323 multiple: t
324 "#]],
325 );
326 }
327
328 #[test]
prelude_is_macro_use()329 fn prelude_is_macro_use() {
330 cov_mark::check!(prelude_is_macro_use);
331 check(
332 r#"
333 //- /main.rs edition:2018 crate:main deps:std
334 structs!(Foo);
335 structs_priv!(Bar);
336 structs_outside!(Out);
337 crate::structs!(MacroNotResolved2);
338
339 mod bar;
340
341 //- /bar.rs
342 structs!(Baz);
343 crate::structs!(MacroNotResolved3);
344
345 //- /lib.rs crate:std
346 pub mod prelude {
347 pub mod rust_2018 {
348 #[macro_export]
349 macro_rules! structs {
350 ($i:ident) => { struct $i; }
351 }
352
353 mod priv_mod {
354 #[macro_export]
355 macro_rules! structs_priv {
356 ($i:ident) => { struct $i; }
357 }
358 }
359 }
360 }
361
362 #[macro_export]
363 macro_rules! structs_outside {
364 ($i:ident) => { struct $i; }
365 }
366 "#,
367 expect![[r#"
368 crate
369 Bar: t v
370 Foo: t v
371 Out: t v
372 bar: t
373
374 crate::bar
375 Baz: t v
376 "#]],
377 );
378 }
379
380 #[test]
prelude_cycle()381 fn prelude_cycle() {
382 check(
383 r#"
384 #[prelude_import]
385 use self::prelude::*;
386
387 declare_mod!();
388
389 mod prelude {
390 macro_rules! declare_mod {
391 () => (mod foo {})
392 }
393 }
394 "#,
395 expect![[r#"
396 crate
397 prelude: t
398
399 crate::prelude
400 "#]],
401 );
402 }
403
404 #[test]
legacy_macro_use_before_def()405 fn legacy_macro_use_before_def() {
406 check(
407 r#"
408 m!();
409
410 macro_rules! m {
411 () => {
412 struct S;
413 }
414 }
415 "#,
416 expect![[r#"
417 crate
418 S: t v
419 "#]],
420 );
421 // FIXME: should not expand. legacy macro scoping is not implemented.
422 }
423
424 #[test]
plain_macros_are_legacy_textual_scoped()425 fn plain_macros_are_legacy_textual_scoped() {
426 check(
427 r#"
428 //- /main.rs
429 mod m1;
430 bar!(NotFoundNotMacroUse);
431
432 mod m2 { foo!(NotFoundBeforeInside2); }
433
434 macro_rules! foo {
435 ($x:ident) => { struct $x; }
436 }
437 foo!(Ok);
438
439 mod m3;
440 foo!(OkShadowStop);
441 bar!(NotFoundMacroUseStop);
442
443 #[macro_use]
444 mod m5 {
445 #[macro_use]
446 mod m6 {
447 macro_rules! foo {
448 ($x:ident) => { fn $x() {} }
449 }
450 }
451 }
452 foo!(ok_double_macro_use_shadow);
453
454 baz!(NotFoundBefore);
455 #[macro_use]
456 mod m7 {
457 macro_rules! baz {
458 ($x:ident) => { struct $x; }
459 }
460 }
461 baz!(OkAfter);
462
463 //- /m1.rs
464 foo!(NotFoundBeforeInside1);
465 macro_rules! bar {
466 ($x:ident) => { struct $x; }
467 }
468
469 //- /m3/mod.rs
470 foo!(OkAfterInside);
471 macro_rules! foo {
472 ($x:ident) => { fn $x() {} }
473 }
474 foo!(ok_shadow);
475
476 #[macro_use]
477 mod m4;
478 bar!(OkMacroUse);
479
480 mod m5;
481 baz!(OkMacroUseInner);
482
483 //- /m3/m4.rs
484 foo!(ok_shadow_deep);
485 macro_rules! bar {
486 ($x:ident) => { struct $x; }
487 }
488 //- /m3/m5.rs
489 #![macro_use]
490 macro_rules! baz {
491 ($x:ident) => { struct $x; }
492 }
493
494
495 "#,
496 expect![[r#"
497 crate
498 NotFoundBefore: t v
499 Ok: t v
500 OkAfter: t v
501 OkShadowStop: t v
502 m1: t
503 m2: t
504 m3: t
505 m5: t
506 m7: t
507 ok_double_macro_use_shadow: v
508
509 crate::m1
510
511 crate::m2
512
513 crate::m3
514 OkAfterInside: t v
515 OkMacroUse: t v
516 OkMacroUseInner: t v
517 m4: t
518 m5: t
519 ok_shadow: v
520
521 crate::m3::m4
522 ok_shadow_deep: v
523
524 crate::m3::m5
525
526 crate::m5
527 m6: t
528
529 crate::m5::m6
530
531 crate::m7
532 "#]],
533 );
534 // FIXME: should not see `NotFoundBefore`
535 }
536
537 #[test]
type_value_macro_live_in_different_scopes()538 fn type_value_macro_live_in_different_scopes() {
539 check(
540 r#"
541 #[macro_export]
542 macro_rules! foo {
543 ($x:ident) => { type $x = (); }
544 }
545
546 foo!(foo);
547 use foo as bar;
548
549 use self::foo as baz;
550 fn baz() {}
551 "#,
552 expect![[r#"
553 crate
554 bar: t m
555 baz: t v m
556 foo: t m
557 "#]],
558 );
559 }
560
561 #[test]
macro_use_can_be_aliased()562 fn macro_use_can_be_aliased() {
563 check(
564 r#"
565 //- /main.rs crate:main deps:foo
566 #[macro_use]
567 extern crate foo;
568
569 foo!(Direct);
570 bar!(Alias);
571
572 //- /lib.rs crate:foo
573 use crate::foo as bar;
574
575 mod m {
576 #[macro_export]
577 macro_rules! foo {
578 ($x:ident) => { struct $x; }
579 }
580 }
581 "#,
582 expect![[r#"
583 crate
584 Alias: t v
585 Direct: t v
586 foo: t
587 "#]],
588 );
589 }
590
591 #[test]
path_qualified_macros()592 fn path_qualified_macros() {
593 check(
594 r#"
595 macro_rules! foo {
596 ($x:ident) => { struct $x; }
597 }
598
599 crate::foo!(NotResolved);
600
601 crate::bar!(OkCrate);
602 bar!(OkPlain);
603 alias1!(NotHere);
604 m::alias1!(OkAliasPlain);
605 m::alias2!(OkAliasSuper);
606 m::alias3!(OkAliasCrate);
607 not_found!(NotFound);
608
609 mod m {
610 #[macro_export]
611 macro_rules! bar {
612 ($x:ident) => { struct $x; }
613 }
614 pub use bar as alias1;
615 pub use super::bar as alias2;
616 pub use crate::bar as alias3;
617 pub use self::bar as not_found;
618 }
619 "#,
620 expect![[r#"
621 crate
622 OkAliasCrate: t v
623 OkAliasPlain: t v
624 OkAliasSuper: t v
625 OkCrate: t v
626 OkPlain: t v
627 bar: m
628 m: t
629
630 crate::m
631 alias1: m
632 alias2: m
633 alias3: m
634 not_found: _
635 "#]],
636 );
637 }
638
639 #[test]
macro_dollar_crate_is_correct_in_item()640 fn macro_dollar_crate_is_correct_in_item() {
641 cov_mark::check!(macro_dollar_crate_self);
642 check(
643 r#"
644 //- /main.rs crate:main deps:foo
645 #[macro_use]
646 extern crate foo;
647
648 #[macro_use]
649 mod m {
650 macro_rules! current {
651 () => {
652 use $crate::Foo as FooSelf;
653 }
654 }
655 }
656
657 struct Foo;
658
659 current!();
660 not_current1!();
661 foo::not_current2!();
662
663 //- /lib.rs crate:foo
664 mod m {
665 #[macro_export]
666 macro_rules! not_current1 {
667 () => {
668 use $crate::Bar;
669 }
670 }
671 }
672
673 #[macro_export]
674 macro_rules! not_current2 {
675 () => {
676 use $crate::Baz;
677 }
678 }
679
680 pub struct Bar;
681 pub struct Baz;
682 "#,
683 expect![[r#"
684 crate
685 Bar: t v
686 Baz: t v
687 Foo: t v
688 FooSelf: t v
689 foo: t
690 m: t
691
692 crate::m
693 "#]],
694 );
695 }
696
697 #[test]
macro_dollar_crate_is_correct_in_indirect_deps()698 fn macro_dollar_crate_is_correct_in_indirect_deps() {
699 cov_mark::check!(macro_dollar_crate_other);
700 // From std
701 check(
702 r#"
703 //- /main.rs edition:2018 crate:main deps:std
704 foo!();
705
706 //- /std.rs crate:std deps:core
707 pub use core::foo;
708
709 pub mod prelude {
710 pub mod rust_2018 {}
711 }
712
713 #[macro_use]
714 mod std_macros;
715
716 //- /core.rs crate:core
717 #[macro_export]
718 macro_rules! foo {
719 () => {
720 use $crate::bar;
721 }
722 }
723
724 pub struct bar;
725 "#,
726 expect![[r#"
727 crate
728 bar: t v
729 "#]],
730 );
731 }
732
733 #[test]
macro_dollar_crate_is_correct_in_derive_meta()734 fn macro_dollar_crate_is_correct_in_derive_meta() {
735 let map = compute_crate_def_map(
736 r#"
737 //- minicore: derive, clone
738 //- /main.rs crate:main deps:lib
739 lib::foo!();
740
741 //- /lib.rs crate:lib
742 #[macro_export]
743 macro_rules! foo {
744 () => {
745 #[derive($crate::Clone)]
746 struct S;
747 }
748 }
749
750 pub use core::clone::Clone;
751 "#,
752 );
753 assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
754 }
755
756 #[test]
expand_derive()757 fn expand_derive() {
758 let map = compute_crate_def_map(
759 r#"
760 //- /main.rs crate:main deps:core
761 use core::Copy;
762
763 #[core::derive(Copy, core::Clone)]
764 struct Foo;
765
766 //- /core.rs crate:core
767 #[rustc_builtin_macro]
768 pub macro derive($item:item) {}
769 #[rustc_builtin_macro]
770 pub macro Copy {}
771 #[rustc_builtin_macro]
772 pub macro Clone {}
773 "#,
774 );
775 assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 2);
776 }
777
778 #[test]
resolve_builtin_derive()779 fn resolve_builtin_derive() {
780 check(
781 r#"
782 //- /main.rs crate:main deps:core
783 use core::*;
784
785 //- /core.rs crate:core
786 #[rustc_builtin_macro]
787 pub macro Clone {}
788
789 pub trait Clone {}
790 "#,
791 expect![[r#"
792 crate
793 Clone: t m
794 "#]],
795 );
796 }
797
798 #[test]
builtin_derive_with_unresolved_attributes_fall_back()799 fn builtin_derive_with_unresolved_attributes_fall_back() {
800 // Tests that we still resolve derives after ignoring an unresolved attribute.
801 cov_mark::check!(unresolved_attribute_fallback);
802 let map = compute_crate_def_map(
803 r#"
804 //- /main.rs crate:main deps:core
805 use core::{Clone, derive};
806
807 #[derive(Clone)]
808 #[unresolved]
809 struct Foo;
810
811 //- /core.rs crate:core
812 #[rustc_builtin_macro]
813 pub macro derive($item:item) {}
814 #[rustc_builtin_macro]
815 pub macro Clone {}
816 "#,
817 );
818 assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
819 }
820
821 #[test]
unresolved_attributes_fall_back_track_per_file_moditems()822 fn unresolved_attributes_fall_back_track_per_file_moditems() {
823 // Tests that we track per-file ModItems when ignoring an unresolved attribute.
824 // Just tracking the `ModItem` leads to `Foo` getting ignored.
825
826 check(
827 r#"
828 //- /main.rs crate:main
829
830 mod submod;
831
832 #[unresolved]
833 struct Foo;
834
835 //- /submod.rs
836 #[unresolved]
837 struct Bar;
838 "#,
839 expect![[r#"
840 crate
841 Foo: t v
842 submod: t
843
844 crate::submod
845 Bar: t v
846 "#]],
847 );
848 }
849
850 #[test]
unresolved_attrs_extern_block_hang()851 fn unresolved_attrs_extern_block_hang() {
852 // Regression test for https://github.com/rust-lang/rust-analyzer/issues/8905
853 check(
854 r#"
855 #[unresolved]
856 extern "C" {
857 #[unresolved]
858 fn f();
859 }
860 "#,
861 expect![[r#"
862 crate
863 f: v
864 "#]],
865 );
866 }
867
868 #[test]
macros_in_extern_block()869 fn macros_in_extern_block() {
870 check(
871 r#"
872 macro_rules! m {
873 () => { static S: u8; };
874 }
875
876 extern {
877 m!();
878 }
879 "#,
880 expect![[r#"
881 crate
882 S: v
883 "#]],
884 );
885 }
886
887 #[test]
resolves_derive_helper()888 fn resolves_derive_helper() {
889 cov_mark::check!(resolved_derive_helper);
890 check(
891 r#"
892 //- /main.rs crate:main deps:proc
893 #[rustc_builtin_macro]
894 pub macro derive($item:item) {}
895
896 #[derive(proc::Derive)]
897 #[helper]
898 #[unresolved]
899 struct S;
900
901 //- /proc.rs crate:proc
902 #![crate_type="proc-macro"]
903 #[proc_macro_derive(Derive, attributes(helper))]
904 fn derive() {}
905 "#,
906 expect![[r#"
907 crate
908 S: t v
909 derive: m
910 "#]],
911 );
912 }
913
914 #[test]
resolves_derive_helper_rustc_builtin_macro()915 fn resolves_derive_helper_rustc_builtin_macro() {
916 cov_mark::check!(resolved_derive_helper);
917 // This is NOT the correct usage of `default` helper attribute, but we don't resolve helper
918 // attributes on non mod items in hir nameres.
919 check(
920 r#"
921 //- minicore: derive, default
922 #[derive(Default)]
923 #[default]
924 enum E {
925 A,
926 B,
927 }
928 "#,
929 expect![[r#"
930 crate
931 E: t
932 "#]],
933 );
934 }
935
936 #[test]
unresolved_attr_with_cfg_attr_hang()937 fn unresolved_attr_with_cfg_attr_hang() {
938 // Another regression test for https://github.com/rust-lang/rust-analyzer/issues/8905
939 check(
940 r#"
941 #[cfg_attr(not(off), unresolved, unresolved)]
942 struct S;
943 "#,
944 expect![[r#"
945 crate
946 S: t v
947 "#]],
948 );
949 }
950
951 #[test]
macro_expansion_overflow()952 fn macro_expansion_overflow() {
953 cov_mark::check!(macro_expansion_overflow);
954 check(
955 r#"
956 macro_rules! a {
957 ($e:expr; $($t:tt)*) => {
958 b!(static = (); $($t)*);
959 };
960 () => {};
961 }
962
963 macro_rules! b {
964 (static = $e:expr; $($t:tt)*) => {
965 a!($e; $($t)*);
966 };
967 () => {};
968 }
969
970 b! { static = #[] ();}
971 "#,
972 expect![[r#"
973 crate
974 "#]],
975 );
976 }
977
978 #[test]
macros_defining_macros()979 fn macros_defining_macros() {
980 check(
981 r#"
982 macro_rules! item {
983 ($item:item) => { $item }
984 }
985
986 item! {
987 macro_rules! indirect_macro { () => { struct S {} } }
988 }
989
990 indirect_macro!();
991 "#,
992 expect![[r#"
993 crate
994 S: t
995 "#]],
996 );
997 }
998
999 #[test]
resolves_proc_macros()1000 fn resolves_proc_macros() {
1001 check(
1002 r#"
1003 #![crate_type="proc-macro"]
1004 struct TokenStream;
1005
1006 #[proc_macro]
1007 pub fn function_like_macro(args: TokenStream) -> TokenStream {
1008 args
1009 }
1010
1011 #[proc_macro_attribute]
1012 pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
1013 item
1014 }
1015
1016 #[proc_macro_derive(DummyTrait)]
1017 pub fn derive_macro(_item: TokenStream) -> TokenStream {
1018 TokenStream
1019 }
1020
1021 #[proc_macro_derive(AnotherTrait, attributes(helper_attr))]
1022 pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
1023 TokenStream
1024 }
1025 "#,
1026 expect![[r#"
1027 crate
1028 AnotherTrait: m
1029 DummyTrait: m
1030 TokenStream: t v
1031 attribute_macro: v m
1032 derive_macro: v
1033 derive_macro_2: v
1034 function_like_macro: v m
1035 "#]],
1036 );
1037 }
1038
1039 #[test]
proc_macro_censoring()1040 fn proc_macro_censoring() {
1041 // Make sure that only proc macros are publicly exported from proc-macro crates.
1042
1043 check(
1044 r#"
1045 //- /main.rs crate:main deps:macros
1046 pub use macros::*;
1047
1048 //- /macros.rs crate:macros
1049 #![crate_type="proc-macro"]
1050 pub struct TokenStream;
1051
1052 #[proc_macro]
1053 pub fn function_like_macro(args: TokenStream) -> TokenStream {
1054 args
1055 }
1056
1057 #[proc_macro_attribute]
1058 pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
1059 item
1060 }
1061
1062 #[proc_macro_derive(DummyTrait)]
1063 pub fn derive_macro(_item: TokenStream) -> TokenStream {
1064 TokenStream
1065 }
1066
1067 #[macro_export]
1068 macro_rules! mbe {
1069 () => {};
1070 }
1071 "#,
1072 expect![[r#"
1073 crate
1074 DummyTrait: m
1075 attribute_macro: m
1076 function_like_macro: m
1077 "#]],
1078 );
1079 }
1080
1081 #[test]
collects_derive_helpers()1082 fn collects_derive_helpers() {
1083 let db = TestDB::with_files(
1084 r#"
1085 #![crate_type="proc-macro"]
1086 struct TokenStream;
1087
1088 #[proc_macro_derive(AnotherTrait, attributes(helper_attr))]
1089 pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
1090 TokenStream
1091 }
1092 "#,
1093 );
1094 let krate = db.crate_graph().iter().next().unwrap();
1095 let def_map = db.crate_def_map(krate);
1096
1097 assert_eq!(def_map.data.exported_derives.len(), 1);
1098 match def_map.data.exported_derives.values().next() {
1099 Some(helpers) => match &**helpers {
1100 [attr] => assert_eq!(attr.display(&db).to_string(), "helper_attr"),
1101 _ => unreachable!(),
1102 },
1103 _ => unreachable!(),
1104 }
1105 }
1106
1107 #[test]
resolve_macro_def()1108 fn resolve_macro_def() {
1109 check(
1110 r#"
1111 pub macro structs($($i:ident),*) {
1112 $(struct $i { field: u32 } )*
1113 }
1114 structs!(Foo);
1115 "#,
1116 expect![[r#"
1117 crate
1118 Foo: t
1119 structs: m
1120 "#]],
1121 );
1122 }
1123
1124 #[test]
macro_in_prelude()1125 fn macro_in_prelude() {
1126 check(
1127 r#"
1128 //- /lib.rs edition:2018 crate:lib deps:std
1129 global_asm!();
1130
1131 //- /std.rs crate:std
1132 pub mod prelude {
1133 pub mod rust_2018 {
1134 pub macro global_asm() {
1135 pub struct S;
1136 }
1137 }
1138 }
1139 "#,
1140 expect![[r#"
1141 crate
1142 S: t v
1143 "#]],
1144 )
1145 }
1146
1147 #[test]
issue9358_bad_macro_stack_overflow()1148 fn issue9358_bad_macro_stack_overflow() {
1149 cov_mark::check!(issue9358_bad_macro_stack_overflow);
1150 check(
1151 r#"
1152 macro_rules! m {
1153 ($cond:expr) => { m!($cond, stringify!($cond)) };
1154 ($cond:expr, $($arg:tt)*) => { $cond };
1155 }
1156 m!(
1157 "#,
1158 expect![[r#"
1159 crate
1160 "#]],
1161 )
1162 }
1163
1164 #[test]
eager_macro_correctly_resolves_contents()1165 fn eager_macro_correctly_resolves_contents() {
1166 // Eager macros resolve any contained macros when expanded. This should work correctly with the
1167 // usual name resolution rules, so both of these `include!`s should include the right file.
1168
1169 check(
1170 r#"
1171 //- /lib.rs
1172 #[rustc_builtin_macro]
1173 macro_rules! include { () => {} }
1174
1175 include!(inner_a!());
1176 include!(crate::inner_b!());
1177
1178 #[macro_export]
1179 macro_rules! inner_a {
1180 () => { "inc_a.rs" };
1181 }
1182 #[macro_export]
1183 macro_rules! inner_b {
1184 () => { "inc_b.rs" };
1185 }
1186 //- /inc_a.rs
1187 struct A;
1188 //- /inc_b.rs
1189 struct B;
1190 "#,
1191 expect![[r#"
1192 crate
1193 A: t v
1194 B: t v
1195 inner_a: m
1196 inner_b: m
1197 "#]],
1198 );
1199 }
1200
1201 #[test]
eager_macro_correctly_resolves_dollar_crate()1202 fn eager_macro_correctly_resolves_dollar_crate() {
1203 // MBE -> eager -> $crate::mbe
1204 check(
1205 r#"
1206 //- /lib.rs
1207 #[rustc_builtin_macro]
1208 macro_rules! include { () => {} }
1209
1210 #[macro_export]
1211 macro_rules! inner {
1212 () => { "inc.rs" };
1213 }
1214
1215 macro_rules! m {
1216 () => { include!($crate::inner!()); };
1217 }
1218
1219 m!();
1220
1221 //- /inc.rs
1222 struct A;
1223 "#,
1224 expect![[r#"
1225 crate
1226 A: t v
1227 inner: m
1228 "#]],
1229 );
1230 // eager -> MBE -> $crate::mbe
1231 check(
1232 r#"
1233 //- /lib.rs
1234 #[rustc_builtin_macro]
1235 macro_rules! include { () => {} }
1236
1237 #[macro_export]
1238 macro_rules! inner {
1239 () => { "inc.rs" };
1240 }
1241
1242 macro_rules! n {
1243 () => {
1244 $crate::inner!()
1245 };
1246 }
1247
1248 include!(n!());
1249
1250 //- /inc.rs
1251 struct A;
1252 "#,
1253 expect![[r#"
1254 crate
1255 A: t v
1256 inner: m
1257 "#]],
1258 );
1259 }
1260
1261 #[test]
macro_use_imports_all_macro_types()1262 fn macro_use_imports_all_macro_types() {
1263 let db = TestDB::with_files(
1264 r#"
1265 //- /main.rs crate:main deps:lib
1266 #[macro_use]
1267 extern crate lib;
1268
1269 //- /lib.rs crate:lib deps:proc
1270 pub use proc::*;
1271
1272 #[macro_export]
1273 macro_rules! legacy { () => () }
1274
1275 pub macro macro20 {}
1276
1277 //- /proc.rs crate:proc
1278 #![crate_type="proc-macro"]
1279
1280 struct TokenStream;
1281
1282 #[proc_macro_attribute]
1283 fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
1284 "#,
1285 );
1286 let krate = db.crate_graph().iter().next().unwrap();
1287 let def_map = db.crate_def_map(krate);
1288
1289 let root_module = &def_map[DefMap::ROOT].scope;
1290 assert!(
1291 root_module.legacy_macros().count() == 0,
1292 "`#[macro_use]` shouldn't bring macros into textual macro scope",
1293 );
1294
1295 let actual = def_map
1296 .macro_use_prelude
1297 .iter()
1298 .map(|(name, _)| name.display(&db).to_string())
1299 .sorted()
1300 .join("\n");
1301
1302 expect![[r#"
1303 legacy
1304 macro20
1305 proc_attr"#]]
1306 .assert_eq(&actual);
1307 }
1308
1309 #[test]
non_prelude_macros_take_precedence_over_macro_use_prelude()1310 fn non_prelude_macros_take_precedence_over_macro_use_prelude() {
1311 check(
1312 r#"
1313 //- /lib.rs edition:2021 crate:lib deps:dep,core
1314 #[macro_use]
1315 extern crate dep;
1316
1317 macro foo() { struct Ok; }
1318 macro bar() { fn ok() {} }
1319
1320 foo!();
1321 bar!();
1322
1323 //- /dep.rs crate:dep
1324 #[macro_export]
1325 macro_rules! foo {
1326 () => { struct NotOk; }
1327 }
1328
1329 //- /core.rs crate:core
1330 pub mod prelude {
1331 pub mod rust_2021 {
1332 #[macro_export]
1333 macro_rules! bar {
1334 () => { fn not_ok() {} }
1335 }
1336 }
1337 }
1338 "#,
1339 expect![[r#"
1340 crate
1341 Ok: t v
1342 bar: m
1343 dep: t
1344 foo: m
1345 ok: v
1346 "#]],
1347 );
1348 }
1349
1350 #[test]
macro_use_prelude_is_eagerly_expanded()1351 fn macro_use_prelude_is_eagerly_expanded() {
1352 // See FIXME in `ModCollector::collect_macro_call()`.
1353 check(
1354 r#"
1355 //- /main.rs crate:main deps:lib
1356 #[macro_use]
1357 extern crate lib;
1358 mk_foo!();
1359 mod a {
1360 foo!();
1361 }
1362 //- /lib.rs crate:lib
1363 #[macro_export]
1364 macro_rules! mk_foo {
1365 () => {
1366 macro_rules! foo {
1367 () => { struct Ok; }
1368 }
1369 }
1370 }
1371 "#,
1372 expect![[r#"
1373 crate
1374 a: t
1375 lib: t
1376
1377 crate::a
1378 Ok: t v
1379 "#]],
1380 );
1381 }
1382
1383 #[test]
macro_sub_namespace()1384 fn macro_sub_namespace() {
1385 let map = compute_crate_def_map(
1386 r#"
1387 //- minicore: derive, clone
1388 macro_rules! Clone { () => {} }
1389 macro_rules! derive { () => {} }
1390
1391 #[derive(Clone)]
1392 struct S;
1393 "#,
1394 );
1395 assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
1396 }
1397
1398 #[test]
macro_sub_namespace2()1399 fn macro_sub_namespace2() {
1400 check(
1401 r#"
1402 //- /main.rs edition:2021 crate:main deps:proc,core
1403 use proc::{foo, bar};
1404
1405 foo!();
1406 bar!();
1407
1408 //- /proc.rs crate:proc
1409 #![crate_type="proc-macro"]
1410 #[proc_macro_derive(foo)]
1411 pub fn foo() {}
1412 #[proc_macro_attribute]
1413 pub fn bar() {}
1414
1415 //- /core.rs crate:core
1416 pub mod prelude {
1417 pub mod rust_2021 {
1418 pub macro foo() {
1419 struct Ok;
1420 }
1421 pub macro bar() {
1422 fn ok() {}
1423 }
1424 }
1425 }
1426 "#,
1427 expect![[r#"
1428 crate
1429 Ok: t v
1430 bar: m
1431 foo: m
1432 ok: v
1433 "#]],
1434 );
1435 }
1436