aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/tests/macros.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres/tests/macros.rs')
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs669
1 files changed, 669 insertions, 0 deletions
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
new file mode 100644
index 000000000..e0fb8bdef
--- /dev/null
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -0,0 +1,669 @@
1use super::*;
2
3#[test]
4fn macro_rules_are_globally_visible() {
5 check(
6 r#"
7//- /lib.rs
8macro_rules! structs {
9 ($($i:ident),*) => {
10 $(struct $i { field: u32 } )*
11 }
12}
13structs!(Foo);
14mod nested;
15
16//- /nested.rs
17structs!(Bar, Baz);
18"#,
19 expect![[r#"
20 crate
21 Foo: t
22 nested: t
23
24 crate::nested
25 Bar: t
26 Baz: t
27 "#]],
28 );
29}
30
31#[test]
32fn macro_rules_can_define_modules() {
33 check(
34 r#"
35//- /lib.rs
36macro_rules! m {
37 ($name:ident) => { mod $name; }
38}
39m!(n1);
40mod m { m!(n3) }
41
42//- /n1.rs
43m!(n2)
44//- /n1/n2.rs
45struct X;
46//- /m/n3.rs
47struct Y;
48"#,
49 expect![[r#"
50 crate
51 m: t
52 n1: t
53
54 crate::m
55 n3: t
56
57 crate::m::n3
58 Y: t v
59
60 crate::n1
61 n2: t
62
63 crate::n1::n2
64 X: t v
65 "#]],
66 );
67}
68
69#[test]
70fn macro_rules_from_other_crates_are_visible() {
71 check(
72 r#"
73//- /main.rs crate:main deps:foo
74foo::structs!(Foo, Bar)
75mod bar;
76
77//- /bar.rs
78use crate::*;
79
80//- /lib.rs crate:foo
81#[macro_export]
82macro_rules! structs {
83 ($($i:ident),*) => {
84 $(struct $i { field: u32 } )*
85 }
86}
87"#,
88 expect![[r#"
89 crate
90 Bar: t
91 Foo: t
92 bar: t
93
94 crate::bar
95 Bar: t
96 Foo: t
97 bar: t
98 "#]],
99 );
100}
101
102#[test]
103fn macro_rules_export_with_local_inner_macros_are_visible() {
104 check(
105 r#"
106//- /main.rs crate:main deps:foo
107foo::structs!(Foo, Bar)
108mod bar;
109
110//- /bar.rs
111use crate::*;
112
113//- /lib.rs crate:foo
114#[macro_export(local_inner_macros)]
115macro_rules! structs {
116 ($($i:ident),*) => {
117 $(struct $i { field: u32 } )*
118 }
119}
120"#,
121 expect![[r#"
122 crate
123 Bar: t
124 Foo: t
125 bar: t
126
127 crate::bar
128 Bar: t
129 Foo: t
130 bar: t
131 "#]],
132 );
133}
134
135#[test]
136fn local_inner_macros_makes_local_macros_usable() {
137 check(
138 r#"
139//- /main.rs crate:main deps:foo
140foo::structs!(Foo, Bar);
141mod bar;
142
143//- /bar.rs
144use crate::*;
145
146//- /lib.rs crate:foo
147#[macro_export(local_inner_macros)]
148macro_rules! structs {
149 ($($i:ident),*) => {
150 inner!($($i),*);
151 }
152}
153#[macro_export]
154macro_rules! inner {
155 ($($i:ident),*) => {
156 $(struct $i { field: u32 } )*
157 }
158}
159"#,
160 expect![[r#"
161 crate
162 Bar: t
163 Foo: t
164 bar: t
165
166 crate::bar
167 Bar: t
168 Foo: t
169 bar: t
170 "#]],
171 );
172}
173
174#[test]
175fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
176 check(
177 r#"
178//- /main.rs crate:main deps:foo
179macro_rules! baz {
180 () => {
181 use foo::bar;
182 }
183}
184foo!();
185bar!();
186baz!();
187
188//- /lib.rs crate:foo
189#[macro_export]
190macro_rules! foo {
191 () => {
192 struct Foo { field: u32 }
193 }
194}
195#[macro_export]
196macro_rules! bar {
197 () => {
198 use foo::foo;
199 }
200}
201"#,
202 expect![[r#"
203 crate
204 Foo: t
205 bar: m
206 foo: m
207 "#]],
208 );
209}
210
211#[test]
212fn macro_rules_from_other_crates_are_visible_with_macro_use() {
213 mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
214 check(
215 r#"
216//- /main.rs crate:main deps:foo
217structs!(Foo);
218structs_priv!(Bar);
219structs_not_exported!(MacroNotResolved1);
220crate::structs!(MacroNotResolved2);
221
222mod bar;
223
224#[macro_use]
225extern crate foo;
226
227//- /bar.rs
228structs!(Baz);
229crate::structs!(MacroNotResolved3);
230
231//- /lib.rs crate:foo
232#[macro_export]
233macro_rules! structs {
234 ($i:ident) => { struct $i; }
235}
236
237macro_rules! structs_not_exported {
238 ($i:ident) => { struct $i; }
239}
240
241mod priv_mod {
242 #[macro_export]
243 macro_rules! structs_priv {
244 ($i:ident) => { struct $i; }
245 }
246}
247"#,
248 expect![[r#"
249 crate
250 Bar: t v
251 Foo: t v
252 bar: t
253 foo: t
254
255 crate::bar
256 Baz: t v
257 "#]],
258 );
259}
260
261#[test]
262fn prelude_is_macro_use() {
263 mark::check!(prelude_is_macro_use);
264 check(
265 r#"
266//- /main.rs crate:main deps:foo
267structs!(Foo);
268structs_priv!(Bar);
269structs_outside!(Out);
270crate::structs!(MacroNotResolved2);
271
272mod bar;
273
274//- /bar.rs
275structs!(Baz);
276crate::structs!(MacroNotResolved3);
277
278//- /lib.rs crate:foo
279#[prelude_import]
280use self::prelude::*;
281
282mod prelude {
283 #[macro_export]
284 macro_rules! structs {
285 ($i:ident) => { struct $i; }
286 }
287
288 mod priv_mod {
289 #[macro_export]
290 macro_rules! structs_priv {
291 ($i:ident) => { struct $i; }
292 }
293 }
294}
295
296#[macro_export]
297macro_rules! structs_outside {
298 ($i:ident) => { struct $i; }
299}
300"#,
301 expect![[r#"
302 crate
303 Bar: t v
304 Foo: t v
305 Out: t v
306 bar: t
307
308 crate::bar
309 Baz: t v
310 "#]],
311 );
312}
313
314#[test]
315fn prelude_cycle() {
316 check(
317 r#"
318#[prelude_import]
319use self::prelude::*;
320
321declare_mod!();
322
323mod prelude {
324 macro_rules! declare_mod {
325 () => (mod foo {})
326 }
327}
328"#,
329 expect![[r#"
330 crate
331 prelude: t
332
333 crate::prelude
334 "#]],
335 );
336}
337
338#[test]
339fn plain_macros_are_legacy_textual_scoped() {
340 check(
341 r#"
342//- /main.rs
343mod m1;
344bar!(NotFoundNotMacroUse);
345
346mod m2 { foo!(NotFoundBeforeInside2); }
347
348macro_rules! foo {
349 ($x:ident) => { struct $x; }
350}
351foo!(Ok);
352
353mod m3;
354foo!(OkShadowStop);
355bar!(NotFoundMacroUseStop);
356
357#[macro_use]
358mod m5 {
359 #[macro_use]
360 mod m6 {
361 macro_rules! foo {
362 ($x:ident) => { fn $x() {} }
363 }
364 }
365}
366foo!(ok_double_macro_use_shadow);
367
368baz!(NotFoundBefore);
369#[macro_use]
370mod m7 {
371 macro_rules! baz {
372 ($x:ident) => { struct $x; }
373 }
374}
375baz!(OkAfter);
376
377//- /m1.rs
378foo!(NotFoundBeforeInside1);
379macro_rules! bar {
380 ($x:ident) => { struct $x; }
381}
382
383//- /m3/mod.rs
384foo!(OkAfterInside);
385macro_rules! foo {
386 ($x:ident) => { fn $x() {} }
387}
388foo!(ok_shadow);
389
390#[macro_use]
391mod m4;
392bar!(OkMacroUse);
393
394//- /m3/m4.rs
395foo!(ok_shadow_deep);
396macro_rules! bar {
397 ($x:ident) => { struct $x; }
398}
399"#,
400 expect![[r#"
401 crate
402 Ok: t v
403 OkAfter: t v
404 OkShadowStop: t v
405 m1: t
406 m2: t
407 m3: t
408 m5: t
409 m7: t
410 ok_double_macro_use_shadow: v
411
412 crate::m7
413
414 crate::m1
415
416 crate::m5
417 m6: t
418
419 crate::m5::m6
420
421 crate::m2
422
423 crate::m3
424 OkAfterInside: t v
425 OkMacroUse: t v
426 m4: t
427 ok_shadow: v
428
429 crate::m3::m4
430 ok_shadow_deep: v
431 "#]],
432 );
433}
434
435#[test]
436fn type_value_macro_live_in_different_scopes() {
437 check(
438 r#"
439#[macro_export]
440macro_rules! foo {
441 ($x:ident) => { type $x = (); }
442}
443
444foo!(foo);
445use foo as bar;
446
447use self::foo as baz;
448fn baz() {}
449"#,
450 expect![[r#"
451 crate
452 bar: t m
453 baz: t v m
454 foo: t m
455 "#]],
456 );
457}
458
459#[test]
460fn macro_use_can_be_aliased() {
461 check(
462 r#"
463//- /main.rs crate:main deps:foo
464#[macro_use]
465extern crate foo;
466
467foo!(Direct);
468bar!(Alias);
469
470//- /lib.rs crate:foo
471use crate::foo as bar;
472
473mod m {
474 #[macro_export]
475 macro_rules! foo {
476 ($x:ident) => { struct $x; }
477 }
478}
479"#,
480 expect![[r#"
481 crate
482 Alias: t v
483 Direct: t v
484 foo: t
485 "#]],
486 );
487}
488
489#[test]
490fn path_qualified_macros() {
491 check(
492 r#"
493macro_rules! foo {
494 ($x:ident) => { struct $x; }
495}
496
497crate::foo!(NotResolved);
498
499crate::bar!(OkCrate);
500bar!(OkPlain);
501alias1!(NotHere);
502m::alias1!(OkAliasPlain);
503m::alias2!(OkAliasSuper);
504m::alias3!(OkAliasCrate);
505not_found!(NotFound);
506
507mod m {
508 #[macro_export]
509 macro_rules! bar {
510 ($x:ident) => { struct $x; }
511 }
512 pub use bar as alias1;
513 pub use super::bar as alias2;
514 pub use crate::bar as alias3;
515 pub use self::bar as not_found;
516}
517"#,
518 expect![[r#"
519 crate
520 OkAliasCrate: t v
521 OkAliasPlain: t v
522 OkAliasSuper: t v
523 OkCrate: t v
524 OkPlain: t v
525 bar: m
526 m: t
527
528 crate::m
529 alias1: m
530 alias2: m
531 alias3: m
532 not_found: _
533 "#]],
534 );
535}
536
537#[test]
538fn macro_dollar_crate_is_correct_in_item() {
539 mark::check!(macro_dollar_crate_self);
540 check(
541 r#"
542//- /main.rs crate:main deps:foo
543#[macro_use]
544extern crate foo;
545
546#[macro_use]
547mod m {
548 macro_rules! current {
549 () => {
550 use $crate::Foo as FooSelf;
551 }
552 }
553}
554
555struct Foo;
556
557current!();
558not_current1!();
559foo::not_current2!();
560
561//- /lib.rs crate:foo
562mod m {
563 #[macro_export]
564 macro_rules! not_current1 {
565 () => {
566 use $crate::Bar;
567 }
568 }
569}
570
571#[macro_export]
572macro_rules! not_current2 {
573 () => {
574 use $crate::Baz;
575 }
576}
577
578struct Bar;
579struct Baz;
580"#,
581 expect![[r#"
582 crate
583 Bar: t v
584 Baz: t v
585 Foo: t v
586 FooSelf: t v
587 foo: t
588 m: t
589
590 crate::m
591 "#]],
592 );
593}
594
595#[test]
596fn macro_dollar_crate_is_correct_in_indirect_deps() {
597 mark::check!(macro_dollar_crate_other);
598 // From std
599 check(
600 r#"
601//- /main.rs crate:main deps:std
602foo!();
603
604//- /std.rs crate:std deps:core
605#[prelude_import]
606use self::prelude::*;
607
608pub use core::foo;
609
610mod prelude {}
611
612#[macro_use]
613mod std_macros;
614
615//- /core.rs crate:core
616#[macro_export]
617macro_rules! foo {
618 () => {
619 use $crate::bar;
620 }
621}
622
623pub struct bar;
624"#,
625 expect![[r#"
626 crate
627 bar: t v
628 "#]],
629 );
630}
631
632#[test]
633fn expand_derive() {
634 let map = compute_crate_def_map(
635 "
636 //- /main.rs
637 #[derive(Copy, Clone)]
638 struct Foo;
639 ",
640 );
641 assert_eq!(map.modules[map.root].scope.impls().len(), 2);
642}
643
644#[test]
645fn macro_expansion_overflow() {
646 mark::check!(macro_expansion_overflow);
647 check(
648 r#"
649macro_rules! a {
650 ($e:expr; $($t:tt)*) => {
651 b!($($t)*);
652 };
653 () => {};
654}
655
656macro_rules! b {
657 (static = $e:expr; $($t:tt)*) => {
658 a!($e; $($t)*);
659 };
660 () => {};
661}
662
663b! { static = #[] (); }
664"#,
665 expect![[r#"
666 crate
667 "#]],
668 );
669}