]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | use expect_test::expect; |
2 | use test_utils::{bench, bench_fixture, skip_slow_tests}; | |
3 | ||
4 | use crate::tests::check_infer_with_mismatches; | |
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 | pub struct S; | |
33 | ||
34 | #[cfg(not(test))] | |
35 | impl S { | |
36 | pub fn foo3(&self) -> i32 { 0 } | |
37 | } | |
38 | ||
39 | #[cfg(test)] | |
40 | impl S { | |
41 | pub 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_def_expanded_in_various_places() { | |
141 | check_infer( | |
142 | r#" | |
143 | macro 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 | |
064997fb FG |
196 | 39..442 '{ ...!(); }': () |
197 | 73..94 'spam!(...am!())': {unknown} | |
198 | 100..119 'for _ ...!() {}': () | |
199 | 104..105 '_': {unknown} | |
200 | 117..119 '{}': () | |
201 | 124..134 '|| spam!()': || -> isize | |
202 | 140..156 'while ...!() {}': () | |
203 | 154..156 '{}': () | |
204 | 161..174 'break spam!()': ! | |
205 | 180..194 'return spam!()': ! | |
206 | 200..254 'match ... }': isize | |
207 | 224..225 '_': isize | |
208 | 259..275 'spam!(...am!())': {unknown} | |
209 | 281..303 'Spam {...m!() }': {unknown} | |
210 | 309..325 'spam!(...am!()]': {unknown} | |
211 | 350..366 'spam!(... usize': usize | |
212 | 372..380 '&spam!()': &isize | |
213 | 386..394 '-spam!()': isize | |
214 | 400..416 'spam!(...pam!()': {unknown} | |
215 | 422..439 'spam!(...pam!()': isize | |
216 | "#]], | |
217 | ); | |
218 | } | |
219 | ||
220 | #[test] | |
221 | fn expr_macro_rules_expanded_in_various_places() { | |
222 | check_infer( | |
223 | r#" | |
224 | macro_rules! spam { | |
225 | () => (1isize); | |
226 | } | |
227 | ||
228 | fn spam() { | |
229 | spam!(); | |
230 | (spam!()); | |
231 | spam!().spam(spam!()); | |
232 | for _ in spam!() {} | |
233 | || spam!(); | |
234 | while spam!() {} | |
235 | break spam!(); | |
236 | return spam!(); | |
237 | match spam!() { | |
238 | _ if spam!() => spam!(), | |
239 | } | |
240 | spam!()(spam!()); | |
241 | Spam { spam: spam!() }; | |
242 | spam!()[spam!()]; | |
243 | await spam!(); | |
244 | spam!() as usize; | |
245 | &spam!(); | |
246 | -spam!(); | |
247 | spam!()..spam!(); | |
248 | spam!() + spam!(); | |
249 | } | |
250 | "#, | |
251 | expect![[r#" | |
252 | !0..6 '1isize': isize | |
253 | !0..6 '1isize': isize | |
254 | !0..6 '1isize': isize | |
255 | !0..6 '1isize': isize | |
256 | !0..6 '1isize': isize | |
257 | !0..6 '1isize': isize | |
258 | !0..6 '1isize': isize | |
259 | !0..6 '1isize': isize | |
260 | !0..6 '1isize': isize | |
261 | !0..6 '1isize': isize | |
262 | !0..6 '1isize': isize | |
263 | !0..6 '1isize': isize | |
264 | !0..6 '1isize': isize | |
265 | !0..6 '1isize': isize | |
266 | !0..6 '1isize': isize | |
267 | !0..6 '1isize': isize | |
268 | !0..6 '1isize': isize | |
269 | !0..6 '1isize': isize | |
270 | !0..6 '1isize': isize | |
271 | !0..6 '1isize': isize | |
272 | !0..6 '1isize': isize | |
273 | !0..6 '1isize': isize | |
274 | !0..6 '1isize': isize | |
275 | !0..6 '1isize': isize | |
276 | !0..6 '1isize': isize | |
064997fb FG |
277 | 53..456 '{ ...!(); }': () |
278 | 87..108 'spam!(...am!())': {unknown} | |
279 | 114..133 'for _ ...!() {}': () | |
280 | 118..119 '_': {unknown} | |
281 | 131..133 '{}': () | |
282 | 138..148 '|| spam!()': || -> isize | |
283 | 154..170 'while ...!() {}': () | |
284 | 168..170 '{}': () | |
285 | 175..188 'break spam!()': ! | |
286 | 194..208 'return spam!()': ! | |
287 | 214..268 'match ... }': isize | |
288 | 238..239 '_': isize | |
289 | 273..289 'spam!(...am!())': {unknown} | |
290 | 295..317 'Spam {...m!() }': {unknown} | |
291 | 323..339 'spam!(...am!()]': {unknown} | |
292 | 364..380 'spam!(... usize': usize | |
293 | 386..394 '&spam!()': &isize | |
294 | 400..408 '-spam!()': isize | |
295 | 414..430 'spam!(...pam!()': {unknown} | |
296 | 436..453 'spam!(...pam!()': isize | |
297 | "#]], | |
298 | ); | |
299 | } | |
300 | ||
301 | #[test] | |
302 | fn expr_macro_expanded_in_stmts() { | |
303 | check_infer( | |
304 | r#" | |
305 | macro_rules! id { ($($es:tt)*) => { $($es)* } } | |
306 | fn foo() { | |
307 | id! { let a = (); } | |
308 | } | |
309 | "#, | |
310 | expect![[r#" | |
064997fb FG |
311 | !3..4 'a': () |
312 | !5..7 '()': () | |
313 | 57..84 '{ ...); } }': () | |
314 | "#]], | |
315 | ); | |
316 | } | |
317 | ||
318 | #[test] | |
f2b60f7d | 319 | fn recursive_macro_expanded_in_stmts() { |
064997fb FG |
320 | check_infer( |
321 | r#" | |
322 | macro_rules! ng { | |
323 | ([$($tts:tt)*]) => { | |
324 | $($tts)*; | |
325 | }; | |
326 | ([$($tts:tt)*] $head:tt $($rest:tt)*) => { | |
327 | ng! { | |
328 | [$($tts)* $head] $($rest)* | |
329 | } | |
330 | }; | |
331 | } | |
332 | fn foo() { | |
333 | ng!([] let a = 3); | |
334 | let b = a; | |
335 | } | |
336 | "#, | |
337 | expect![[r#" | |
064997fb FG |
338 | !3..4 'a': i32 |
339 | !5..6 '3': i32 | |
340 | 196..237 '{ ...= a; }': () | |
341 | 229..230 'b': i32 | |
342 | 233..234 'a': i32 | |
343 | "#]], | |
344 | ); | |
345 | } | |
346 | ||
347 | #[test] | |
348 | fn recursive_inner_item_macro_rules() { | |
349 | check_infer( | |
350 | r#" | |
351 | macro_rules! mac { | |
352 | () => { mac!($)}; | |
353 | ($x:tt) => { macro_rules! blub { () => { 1 }; } }; | |
354 | } | |
355 | fn foo() { | |
356 | mac!(); | |
357 | let a = blub!(); | |
358 | } | |
359 | "#, | |
360 | expect![[r#" | |
361 | !0..1 '1': i32 | |
064997fb FG |
362 | 107..143 '{ ...!(); }': () |
363 | 129..130 'a': i32 | |
364 | "#]], | |
365 | ); | |
366 | } | |
367 | ||
368 | #[test] | |
369 | fn infer_macro_defining_block_with_items() { | |
370 | check_infer( | |
371 | r#" | |
372 | macro_rules! foo { | |
373 | () => {{ | |
374 | fn bar() -> usize { 0 } | |
375 | bar() | |
376 | }}; | |
377 | } | |
378 | fn main() { | |
379 | let _a = foo!(); | |
380 | } | |
381 | "#, | |
382 | expect![[r#" | |
383 | !15..18 '{0}': usize | |
384 | !16..17 '0': usize | |
385 | !0..24 '{fnbar...bar()}': usize | |
386 | !18..21 'bar': fn bar() -> usize | |
387 | !18..23 'bar()': usize | |
388 | 98..122 '{ ...!(); }': () | |
389 | 108..110 '_a': usize | |
390 | "#]], | |
391 | ); | |
392 | } | |
393 | ||
394 | #[test] | |
395 | fn infer_type_value_macro_having_same_name() { | |
396 | check_infer( | |
397 | r#" | |
398 | #[macro_export] | |
399 | macro_rules! foo { | |
400 | () => { | |
401 | mod foo { | |
402 | pub use super::foo; | |
403 | } | |
404 | }; | |
405 | ($x:tt) => { | |
406 | $x | |
407 | }; | |
408 | } | |
409 | ||
410 | foo!(); | |
411 | ||
412 | fn foo() { | |
413 | let foo = foo::foo!(42i32); | |
414 | } | |
415 | "#, | |
416 | expect![[r#" | |
417 | !0..5 '42i32': i32 | |
418 | 170..205 '{ ...32); }': () | |
419 | 180..183 'foo': i32 | |
420 | "#]], | |
421 | ); | |
422 | } | |
423 | ||
424 | #[test] | |
425 | fn processes_impls_generated_by_macros() { | |
426 | check_types( | |
427 | r#" | |
428 | macro_rules! m { | |
429 | ($ident:ident) => (impl Trait for $ident {}) | |
430 | } | |
431 | trait Trait { fn foo(self) -> u128 { 0 } } | |
432 | struct S; | |
433 | m!(S); | |
434 | fn test() { S.foo(); } | |
435 | //^^^^^^^ u128 | |
436 | "#, | |
437 | ); | |
438 | } | |
439 | ||
440 | #[test] | |
441 | fn infer_assoc_items_generated_by_macros() { | |
442 | check_types( | |
443 | r#" | |
444 | macro_rules! m { | |
445 | () => (fn foo(&self) -> u128 {0}) | |
446 | } | |
447 | struct S; | |
448 | impl S { | |
449 | m!(); | |
450 | } | |
451 | ||
452 | fn test() { S.foo(); } | |
453 | //^^^^^^^ u128 | |
454 | "#, | |
455 | ); | |
456 | } | |
457 | ||
458 | #[test] | |
459 | fn infer_assoc_items_generated_by_macros_chain() { | |
460 | check_types( | |
461 | r#" | |
462 | macro_rules! m_inner { | |
463 | () => {fn foo(&self) -> u128 {0}} | |
464 | } | |
465 | macro_rules! m { | |
466 | () => {m_inner!();} | |
467 | } | |
468 | ||
469 | struct S; | |
470 | impl S { | |
471 | m!(); | |
472 | } | |
473 | ||
474 | fn test() { S.foo(); } | |
475 | //^^^^^^^ u128 | |
476 | "#, | |
477 | ); | |
478 | } | |
479 | ||
480 | #[test] | |
481 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { | |
482 | check_types( | |
483 | r#" | |
484 | //- /main.rs crate:main deps:foo | |
485 | fn test() { | |
486 | let x = (foo::foo!(1), foo::foo!(2)); | |
487 | x; | |
488 | } //^ (i32, usize) | |
489 | ||
490 | //- /lib.rs crate:foo | |
491 | #[macro_export] | |
492 | macro_rules! foo { | |
493 | (1) => { $crate::bar!() }; | |
494 | (2) => { 1 + $crate::baz() }; | |
495 | } | |
496 | ||
497 | #[macro_export] | |
498 | macro_rules! bar { | |
499 | () => { 42 } | |
500 | } | |
501 | ||
502 | pub fn baz() -> usize { 31usize } | |
503 | "#, | |
504 | ); | |
505 | } | |
506 | ||
507 | #[test] | |
508 | fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() { | |
509 | check_types( | |
510 | r#" | |
511 | //- /main.rs crate:main deps:foo | |
512 | use foo::Trait; | |
513 | ||
514 | fn test() { | |
515 | let msg = foo::Message(foo::MessageRef); | |
516 | let r = msg.deref(); | |
517 | r; | |
518 | //^ &MessageRef | |
519 | } | |
520 | ||
521 | //- /lib.rs crate:foo | |
522 | pub struct MessageRef; | |
523 | pub struct Message(MessageRef); | |
524 | ||
525 | pub trait Trait { | |
526 | type Target; | |
527 | fn deref(&self) -> &Self::Target; | |
528 | } | |
529 | ||
530 | #[macro_export] | |
531 | macro_rules! expand { | |
532 | () => { | |
533 | impl Trait for Message { | |
534 | type Target = $crate::MessageRef; | |
535 | fn deref(&self) -> &Self::Target { | |
536 | &self.0 | |
537 | } | |
538 | } | |
539 | } | |
540 | } | |
541 | ||
542 | expand!(); | |
543 | "#, | |
544 | ); | |
545 | } | |
546 | ||
547 | #[test] | |
548 | fn infer_macro_with_dollar_crate_in_def_site() { | |
549 | check_types( | |
550 | r#" | |
551 | //- /main.rs crate:main deps:foo | |
552 | use foo::expand; | |
553 | ||
554 | macro_rules! list { | |
555 | ($($tt:tt)*) => { $($tt)* } | |
556 | } | |
557 | ||
558 | fn test() { | |
559 | let r = expand!(); | |
560 | r; | |
561 | //^ u128 | |
562 | } | |
563 | ||
564 | //- /lib.rs crate:foo | |
565 | #[macro_export] | |
566 | macro_rules! expand { | |
567 | () => { list!($crate::m!()) }; | |
568 | } | |
569 | ||
570 | #[macro_export] | |
571 | macro_rules! m { | |
572 | () => { 0u128 }; | |
573 | } | |
574 | "#, | |
575 | ); | |
576 | } | |
577 | ||
578 | #[test] | |
579 | fn infer_type_value_non_legacy_macro_use_as() { | |
580 | check_infer( | |
581 | r#" | |
582 | mod m { | |
583 | macro_rules! _foo { | |
584 | ($x:ident) => { type $x = u64; } | |
585 | } | |
586 | pub(crate) use _foo as foo; | |
587 | } | |
588 | ||
589 | m::foo!(foo); | |
590 | use foo as bar; | |
591 | fn f() -> bar { 0 } | |
592 | fn main() { | |
593 | let _a = f(); | |
594 | } | |
595 | "#, | |
596 | expect![[r#" | |
597 | 158..163 '{ 0 }': u64 | |
598 | 160..161 '0': u64 | |
599 | 174..196 '{ ...f(); }': () | |
600 | 184..186 '_a': u64 | |
601 | 190..191 'f': fn f() -> u64 | |
602 | 190..193 'f()': u64 | |
603 | "#]], | |
604 | ); | |
605 | } | |
606 | ||
607 | #[test] | |
608 | fn infer_local_macro() { | |
609 | check_infer( | |
610 | r#" | |
611 | fn main() { | |
612 | macro_rules! foo { | |
613 | () => { 1usize } | |
614 | } | |
615 | let _a = foo!(); | |
616 | } | |
617 | "#, | |
618 | expect![[r#" | |
619 | !0..6 '1usize': usize | |
620 | 10..89 '{ ...!(); }': () | |
621 | 74..76 '_a': usize | |
622 | "#]], | |
623 | ); | |
624 | } | |
625 | ||
626 | #[test] | |
627 | fn infer_local_inner_macros() { | |
628 | check_types( | |
629 | r#" | |
630 | //- /main.rs crate:main deps:foo | |
631 | fn test() { | |
632 | let x = foo::foo!(1); | |
633 | x; | |
634 | } //^ i32 | |
635 | ||
636 | //- /lib.rs crate:foo | |
637 | #[macro_export(local_inner_macros)] | |
638 | macro_rules! foo { | |
639 | (1) => { bar!() }; | |
640 | } | |
641 | ||
642 | #[macro_export] | |
643 | macro_rules! bar { | |
644 | () => { 42 } | |
645 | } | |
646 | ||
647 | "#, | |
648 | ); | |
649 | } | |
650 | ||
651 | #[test] | |
652 | fn infer_builtin_macros_line() { | |
653 | check_infer( | |
654 | r#" | |
655 | #[rustc_builtin_macro] | |
656 | macro_rules! line {() => {}} | |
657 | ||
658 | fn main() { | |
659 | let x = line!(); | |
660 | } | |
661 | "#, | |
662 | expect![[r#" | |
663 | !0..1 '0': i32 | |
664 | 63..87 '{ ...!(); }': () | |
665 | 73..74 'x': i32 | |
666 | "#]], | |
667 | ); | |
668 | } | |
669 | ||
670 | #[test] | |
671 | fn infer_builtin_macros_file() { | |
672 | check_infer( | |
673 | r#" | |
674 | #[rustc_builtin_macro] | |
675 | macro_rules! file {() => {}} | |
676 | ||
677 | fn main() { | |
678 | let x = file!(); | |
679 | } | |
680 | "#, | |
681 | expect![[r#" | |
682 | !0..2 '""': &str | |
683 | 63..87 '{ ...!(); }': () | |
684 | 73..74 'x': &str | |
685 | "#]], | |
686 | ); | |
687 | } | |
688 | ||
689 | #[test] | |
690 | fn infer_builtin_macros_column() { | |
691 | check_infer( | |
692 | r#" | |
693 | #[rustc_builtin_macro] | |
694 | macro_rules! column {() => {}} | |
695 | ||
696 | fn main() { | |
697 | let x = column!(); | |
698 | } | |
699 | "#, | |
700 | expect![[r#" | |
701 | !0..1 '0': i32 | |
702 | 65..91 '{ ...!(); }': () | |
703 | 75..76 'x': i32 | |
704 | "#]], | |
705 | ); | |
706 | } | |
707 | ||
708 | #[test] | |
709 | fn infer_builtin_macros_concat() { | |
710 | check_infer( | |
711 | r#" | |
712 | #[rustc_builtin_macro] | |
713 | macro_rules! concat {() => {}} | |
714 | ||
715 | fn main() { | |
716 | let x = concat!("hello", concat!("world", "!")); | |
717 | } | |
718 | "#, | |
719 | expect![[r#" | |
720 | !0..13 '"helloworld!"': &str | |
721 | 65..121 '{ ...")); }': () | |
722 | 75..76 'x': &str | |
723 | "#]], | |
724 | ); | |
725 | } | |
726 | ||
727 | #[test] | |
728 | fn infer_builtin_macros_include() { | |
729 | check_types( | |
730 | r#" | |
731 | //- /main.rs | |
732 | #[rustc_builtin_macro] | |
733 | macro_rules! include {() => {}} | |
734 | ||
735 | include!("foo.rs"); | |
736 | ||
737 | fn main() { | |
738 | bar(); | |
739 | } //^^^^^ u32 | |
740 | ||
741 | //- /foo.rs | |
742 | fn bar() -> u32 {0} | |
743 | "#, | |
744 | ); | |
745 | } | |
746 | ||
747 | #[test] | |
748 | fn infer_builtin_macros_include_expression() { | |
749 | check_types( | |
750 | r#" | |
751 | //- /main.rs | |
752 | #[rustc_builtin_macro] | |
753 | macro_rules! include {() => {}} | |
754 | fn main() { | |
755 | let i = include!("bla.rs"); | |
756 | i; | |
757 | //^ i32 | |
758 | } | |
759 | //- /bla.rs | |
760 | 0 | |
761 | "#, | |
762 | ) | |
763 | } | |
764 | ||
765 | #[test] | |
766 | fn infer_builtin_macros_include_child_mod() { | |
767 | check_types( | |
768 | r#" | |
769 | //- /main.rs | |
770 | #[rustc_builtin_macro] | |
771 | macro_rules! include {() => {}} | |
772 | ||
773 | include!("f/foo.rs"); | |
774 | ||
775 | fn main() { | |
776 | bar::bar(); | |
777 | } //^^^^^^^^^^ u32 | |
778 | ||
779 | //- /f/foo.rs | |
780 | pub mod bar; | |
781 | ||
782 | //- /f/bar.rs | |
783 | pub fn bar() -> u32 {0} | |
784 | "#, | |
785 | ); | |
786 | } | |
787 | ||
788 | #[test] | |
789 | fn infer_builtin_macros_include_str() { | |
790 | check_types( | |
791 | r#" | |
792 | //- /main.rs | |
793 | #[rustc_builtin_macro] | |
794 | macro_rules! include_str {() => {}} | |
795 | ||
796 | fn main() { | |
797 | let a = include_str!("foo.rs"); | |
798 | a; | |
799 | } //^ &str | |
800 | ||
801 | //- /foo.rs | |
802 | hello | |
803 | "#, | |
804 | ); | |
805 | } | |
806 | ||
807 | #[test] | |
808 | fn infer_builtin_macros_include_str_with_lazy_nested() { | |
809 | check_types( | |
810 | r#" | |
811 | //- /main.rs | |
812 | #[rustc_builtin_macro] | |
813 | macro_rules! concat {() => {}} | |
814 | #[rustc_builtin_macro] | |
815 | macro_rules! include_str {() => {}} | |
816 | ||
817 | macro_rules! m { | |
818 | ($x:expr) => { | |
819 | concat!("foo", $x) | |
820 | }; | |
821 | } | |
822 | ||
823 | fn main() { | |
824 | let a = include_str!(m!(".rs")); | |
825 | a; | |
826 | } //^ &str | |
827 | ||
828 | //- /foo.rs | |
829 | hello | |
830 | "#, | |
831 | ); | |
832 | } | |
833 | ||
834 | #[test] | |
835 | fn benchmark_include_macro() { | |
836 | if skip_slow_tests() { | |
837 | return; | |
838 | } | |
839 | let data = bench_fixture::big_struct(); | |
840 | let fixture = r#" | |
841 | //- /main.rs | |
842 | #[rustc_builtin_macro] | |
843 | macro_rules! include {() => {}} | |
844 | ||
845 | include!("foo.rs"); | |
846 | ||
847 | fn main() { | |
848 | RegisterBlock { }; | |
849 | //^^^^^^^^^^^^^^^^^ RegisterBlock | |
850 | } | |
851 | "#; | |
852 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data); | |
853 | ||
854 | { | |
855 | let _b = bench("include macro"); | |
856 | check_types(&fixture); | |
857 | } | |
858 | } | |
859 | ||
860 | #[test] | |
861 | fn infer_builtin_macros_include_concat() { | |
862 | check_types( | |
863 | r#" | |
864 | //- /main.rs | |
865 | #[rustc_builtin_macro] | |
866 | macro_rules! include {() => {}} | |
867 | ||
868 | #[rustc_builtin_macro] | |
869 | macro_rules! concat {() => {}} | |
870 | ||
871 | include!(concat!("f", "oo.rs")); | |
872 | ||
873 | fn main() { | |
874 | bar(); | |
875 | } //^^^^^ u32 | |
876 | ||
877 | //- /foo.rs | |
878 | fn bar() -> u32 {0} | |
879 | "#, | |
880 | ); | |
881 | } | |
882 | ||
883 | #[test] | |
884 | fn infer_builtin_macros_include_concat_with_bad_env_should_failed() { | |
885 | check_types( | |
886 | r#" | |
887 | //- /main.rs | |
888 | #[rustc_builtin_macro] | |
889 | macro_rules! include {() => {}} | |
890 | ||
891 | #[rustc_builtin_macro] | |
892 | macro_rules! concat {() => {}} | |
893 | ||
894 | #[rustc_builtin_macro] | |
895 | macro_rules! env {() => {}} | |
896 | ||
897 | include!(concat!(env!("OUT_DIR"), "/foo.rs")); | |
898 | ||
899 | fn main() { | |
900 | bar(); | |
901 | } //^^^^^ {unknown} | |
902 | ||
903 | //- /foo.rs | |
904 | fn bar() -> u32 {0} | |
905 | "#, | |
906 | ); | |
907 | } | |
908 | ||
909 | #[test] | |
910 | fn infer_builtin_macros_include_itself_should_failed() { | |
911 | check_types( | |
912 | r#" | |
913 | #[rustc_builtin_macro] | |
914 | macro_rules! include {() => {}} | |
915 | ||
916 | include!("main.rs"); | |
917 | ||
918 | fn main() { | |
919 | 0; | |
920 | } //^ i32 | |
921 | "#, | |
922 | ); | |
923 | } | |
924 | ||
925 | #[test] | |
926 | fn infer_builtin_macros_concat_with_lazy() { | |
927 | check_infer( | |
928 | r#" | |
929 | macro_rules! hello {() => {"hello"}} | |
930 | ||
931 | #[rustc_builtin_macro] | |
932 | macro_rules! concat {() => {}} | |
933 | ||
934 | fn main() { | |
935 | let x = concat!(hello!(), concat!("world", "!")); | |
936 | } | |
937 | "#, | |
938 | expect![[r#" | |
939 | !0..13 '"helloworld!"': &str | |
940 | 103..160 '{ ...")); }': () | |
941 | 113..114 'x': &str | |
942 | "#]], | |
943 | ); | |
944 | } | |
945 | ||
946 | #[test] | |
947 | fn infer_builtin_macros_env() { | |
948 | check_infer( | |
949 | r#" | |
950 | //- /main.rs env:foo=bar | |
951 | #[rustc_builtin_macro] | |
952 | macro_rules! env {() => {}} | |
953 | ||
954 | fn main() { | |
955 | let x = env!("foo"); | |
956 | } | |
957 | "#, | |
958 | expect![[r#" | |
959 | !0..22 '"__RA_...TED__"': &str | |
960 | 62..90 '{ ...o"); }': () | |
961 | 72..73 'x': &str | |
962 | "#]], | |
963 | ); | |
964 | } | |
965 | ||
966 | #[test] | |
967 | fn infer_derive_clone_simple() { | |
968 | check_types( | |
969 | r#" | |
970 | //- minicore: derive, clone | |
971 | #[derive(Clone)] | |
972 | struct S; | |
973 | fn test() { | |
974 | S.clone(); | |
975 | } //^^^^^^^^^ S | |
976 | "#, | |
977 | ); | |
978 | } | |
979 | ||
980 | #[test] | |
981 | fn infer_derive_clone_with_params() { | |
982 | check_types( | |
983 | r#" | |
984 | //- minicore: clone, derive | |
985 | #[derive(Clone)] | |
986 | struct S; | |
987 | #[derive(Clone)] | |
988 | struct Wrapper<T>(T); | |
989 | struct NonClone; | |
990 | fn test() { | |
991 | let x = (Wrapper(S).clone(), Wrapper(NonClone).clone()); | |
992 | x; | |
993 | //^ (Wrapper<S>, {unknown}) | |
994 | } | |
995 | "#, | |
996 | ); | |
997 | } | |
998 | ||
999 | #[test] | |
1000 | fn infer_custom_derive_simple() { | |
1001 | // FIXME: this test current now do nothing | |
1002 | check_types( | |
1003 | r#" | |
1004 | //- minicore: derive | |
1005 | use foo::Foo; | |
1006 | ||
1007 | #[derive(Foo)] | |
1008 | struct S{} | |
1009 | ||
1010 | fn test() { | |
1011 | S{}; | |
1012 | } //^^^ S | |
1013 | "#, | |
1014 | ); | |
1015 | } | |
1016 | ||
1017 | #[test] | |
1018 | fn macro_in_arm() { | |
1019 | check_infer( | |
1020 | r#" | |
1021 | macro_rules! unit { | |
1022 | () => { () }; | |
1023 | } | |
1024 | ||
1025 | fn main() { | |
1026 | let x = match () { | |
1027 | unit!() => 92u32, | |
1028 | }; | |
1029 | } | |
1030 | "#, | |
1031 | expect![[r#" | |
1032 | !0..2 '()': () | |
1033 | 51..110 '{ ... }; }': () | |
1034 | 61..62 'x': u32 | |
1035 | 65..107 'match ... }': u32 | |
1036 | 71..73 '()': () | |
1037 | 95..100 '92u32': u32 | |
1038 | "#]], | |
1039 | ); | |
1040 | } | |
1041 | ||
1042 | #[test] | |
1043 | fn macro_in_type_alias_position() { | |
1044 | check_infer( | |
1045 | r#" | |
1046 | macro_rules! U32 { | |
1047 | () => { u32 }; | |
1048 | } | |
1049 | ||
1050 | trait Foo { | |
1051 | type Ty; | |
1052 | } | |
1053 | ||
1054 | impl<T> Foo for T { | |
1055 | type Ty = U32!(); | |
1056 | } | |
1057 | ||
1058 | type TayTo = U32!(); | |
1059 | ||
1060 | fn testy() { | |
1061 | let a: <() as Foo>::Ty; | |
1062 | let b: TayTo; | |
1063 | } | |
1064 | "#, | |
1065 | expect![[r#" | |
1066 | 147..196 '{ ...yTo; }': () | |
1067 | 157..158 'a': u32 | |
1068 | 185..186 'b': u32 | |
1069 | "#]], | |
1070 | ); | |
1071 | } | |
1072 | ||
1073 | #[test] | |
1074 | fn nested_macro_in_type_alias_position() { | |
1075 | check_infer( | |
1076 | r#" | |
1077 | macro_rules! U32Inner2 { | |
1078 | () => { u32 }; | |
1079 | } | |
1080 | ||
1081 | macro_rules! U32Inner1 { | |
1082 | () => { U32Inner2!() }; | |
1083 | } | |
1084 | ||
1085 | macro_rules! U32 { | |
1086 | () => { U32Inner1!() }; | |
1087 | } | |
1088 | ||
1089 | trait Foo { | |
1090 | type Ty; | |
1091 | } | |
1092 | ||
1093 | impl<T> Foo for T { | |
1094 | type Ty = U32!(); | |
1095 | } | |
1096 | ||
1097 | type TayTo = U32!(); | |
1098 | ||
1099 | fn testy() { | |
1100 | let a: <() as Foo>::Ty; | |
1101 | let b: TayTo; | |
1102 | } | |
1103 | "#, | |
1104 | expect![[r#" | |
1105 | 259..308 '{ ...yTo; }': () | |
1106 | 269..270 'a': u32 | |
1107 | 297..298 'b': u32 | |
1108 | "#]], | |
1109 | ); | |
1110 | } | |
1111 | ||
1112 | #[test] | |
1113 | fn macros_in_type_alias_position_generics() { | |
1114 | check_infer( | |
1115 | r#" | |
1116 | struct Foo<A, B>(A, B); | |
1117 | ||
1118 | macro_rules! U32 { | |
1119 | () => { u32 }; | |
1120 | } | |
1121 | ||
1122 | macro_rules! Bar { | |
1123 | () => { Foo<U32!(), U32!()> }; | |
1124 | } | |
1125 | ||
1126 | trait Moo { | |
1127 | type Ty; | |
1128 | } | |
1129 | ||
1130 | impl<T> Moo for T { | |
1131 | type Ty = Bar!(); | |
1132 | } | |
1133 | ||
1134 | type TayTo = Bar!(); | |
1135 | ||
1136 | fn main() { | |
1137 | let a: <() as Moo>::Ty; | |
1138 | let b: TayTo; | |
1139 | } | |
1140 | "#, | |
1141 | expect![[r#" | |
1142 | 228..277 '{ ...yTo; }': () | |
1143 | 238..239 'a': Foo<u32, u32> | |
1144 | 266..267 'b': Foo<u32, u32> | |
1145 | "#]], | |
1146 | ); | |
1147 | } | |
1148 | ||
1149 | #[test] | |
1150 | fn macros_in_type_position() { | |
1151 | check_infer( | |
1152 | r#" | |
1153 | struct Foo<A, B>(A, B); | |
1154 | ||
1155 | macro_rules! U32 { | |
1156 | () => { u32 }; | |
1157 | } | |
1158 | ||
1159 | macro_rules! Bar { | |
1160 | () => { Foo<U32!(), U32!()> }; | |
1161 | } | |
1162 | ||
1163 | fn main() { | |
1164 | let a: Bar!(); | |
1165 | } | |
1166 | "#, | |
1167 | expect![[r#" | |
1168 | 133..155 '{ ...!(); }': () | |
1169 | 143..144 'a': Foo<u32, u32> | |
1170 | "#]], | |
1171 | ); | |
1172 | } | |
1173 | ||
1174 | #[test] | |
1175 | fn macros_in_type_generics() { | |
1176 | check_infer( | |
1177 | r#" | |
1178 | struct Foo<A, B>(A, B); | |
1179 | ||
1180 | macro_rules! U32 { | |
1181 | () => { u32 }; | |
1182 | } | |
1183 | ||
1184 | macro_rules! Bar { | |
1185 | () => { Foo<U32!(), U32!()> }; | |
1186 | } | |
1187 | ||
1188 | trait Moo { | |
1189 | type Ty; | |
1190 | } | |
1191 | ||
1192 | impl<T> Moo for T { | |
1193 | type Ty = Foo<Bar!(), Bar!()>; | |
1194 | } | |
1195 | ||
1196 | type TayTo = Foo<Bar!(), U32!()>; | |
1197 | ||
1198 | fn main() { | |
1199 | let a: <() as Moo>::Ty; | |
1200 | let b: TayTo; | |
1201 | } | |
1202 | "#, | |
1203 | expect![[r#" | |
1204 | 254..303 '{ ...yTo; }': () | |
1205 | 264..265 'a': Foo<Foo<u32, u32>, Foo<u32, u32>> | |
1206 | 292..293 'b': Foo<Foo<u32, u32>, u32> | |
1207 | "#]], | |
1208 | ); | |
1209 | } | |
1210 | ||
1211 | #[test] | |
1212 | fn infinitely_recursive_macro_type() { | |
1213 | check_infer( | |
1214 | r#" | |
1215 | struct Bar<T, X>(T, X); | |
1216 | ||
1217 | macro_rules! Foo { | |
1218 | () => { Foo!() } | |
1219 | } | |
1220 | ||
1221 | macro_rules! U32 { | |
1222 | () => { u32 } | |
1223 | } | |
1224 | ||
1225 | type A = Foo!(); | |
1226 | type B = Bar<Foo!(), U32!()>; | |
1227 | ||
1228 | fn main() { | |
1229 | let a: A; | |
1230 | let b: B; | |
1231 | } | |
1232 | "#, | |
1233 | expect![[r#" | |
1234 | 166..197 '{ ...: B; }': () | |
1235 | 176..177 'a': {unknown} | |
1236 | 190..191 'b': Bar<{unknown}, u32> | |
1237 | "#]], | |
1238 | ); | |
1239 | } | |
1240 | ||
1241 | #[test] | |
1242 | fn cfg_tails() { | |
1243 | check_infer_with_mismatches( | |
1244 | r#" | |
1245 | //- /lib.rs crate:foo cfg:feature=foo | |
1246 | struct S {} | |
1247 | ||
1248 | impl S { | |
1249 | fn new2(bar: u32) -> Self { | |
1250 | #[cfg(feature = "foo")] | |
1251 | { Self { } } | |
1252 | #[cfg(not(feature = "foo"))] | |
1253 | { Self { } } | |
1254 | } | |
1255 | } | |
1256 | "#, | |
1257 | expect![[r#" | |
1258 | 34..37 'bar': u32 | |
1259 | 52..170 '{ ... }': S | |
1260 | 62..106 '#[cfg(... { } }': S | |
1261 | 96..104 'Self { }': S | |
1262 | "#]], | |
1263 | ); | |
1264 | } | |
1265 | ||
1266 | #[test] | |
1267 | fn infer_in_unexpandable_attr_proc_macro_1() { | |
1268 | check_types( | |
1269 | r#" | |
1270 | //- /main.rs crate:main deps:mac | |
1271 | #[mac::attr_macro] | |
1272 | fn foo() { | |
1273 | let xxx = 1; | |
1274 | //^^^ i32 | |
1275 | } | |
1276 | ||
1277 | //- /mac.rs crate:mac | |
1278 | #![crate_type="proc-macro"] | |
1279 | #[proc_macro_attribute] | |
1280 | pub fn attr_macro() {} | |
1281 | "#, | |
1282 | ); | |
1283 | } | |
1284 | ||
1285 | #[test] | |
1286 | fn infer_in_unexpandable_attr_proc_macro_in_impl() { | |
1287 | check_types( | |
1288 | r#" | |
1289 | //- /main.rs crate:main deps:mac | |
1290 | struct Foo; | |
1291 | impl Foo { | |
1292 | #[mac::attr_macro] | |
1293 | fn foo() { | |
1294 | let xxx = 1; | |
1295 | //^^^ i32 | |
1296 | } | |
1297 | } | |
1298 | ||
1299 | //- /mac.rs crate:mac | |
1300 | #![crate_type="proc-macro"] | |
1301 | #[proc_macro_attribute] | |
1302 | pub fn attr_macro() {} | |
1303 | "#, | |
1304 | ); | |
1305 | } | |
1306 | ||
1307 | #[test] | |
1308 | fn infer_in_unexpandable_attr_proc_macro_in_trait() { | |
1309 | check_types( | |
1310 | r#" | |
1311 | //- /main.rs crate:main deps:mac | |
1312 | trait Foo { | |
1313 | #[mac::attr_macro] | |
1314 | fn foo() { | |
1315 | let xxx = 1; | |
1316 | //^^^ i32 | |
1317 | } | |
1318 | } | |
1319 | ||
1320 | //- /mac.rs crate:mac | |
1321 | #![crate_type="proc-macro"] | |
1322 | #[proc_macro_attribute] | |
1323 | pub fn attr_macro() {} | |
1324 | "#, | |
1325 | ); | |
1326 | } |