diff options
Diffstat (limited to 'crates/hir_ty/src/tests/macros.rs')
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 787 |
1 files changed, 787 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs new file mode 100644 index 000000000..d887c7a79 --- /dev/null +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -0,0 +1,787 @@ | |||
1 | use std::fs; | ||
2 | |||
3 | use expect::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_type_value_non_legacy_macro_use_as() { | ||
375 | check_infer( | ||
376 | r#" | ||
377 | mod m { | ||
378 | macro_rules! _foo { | ||
379 | ($x:ident) => { type $x = u64; } | ||
380 | } | ||
381 | pub(crate) use _foo as foo; | ||
382 | } | ||
383 | |||
384 | m::foo!(foo); | ||
385 | use foo as bar; | ||
386 | fn f() -> bar { 0 } | ||
387 | fn main() { | ||
388 | let _a = f(); | ||
389 | } | ||
390 | "#, | ||
391 | expect![[r#" | ||
392 | 158..163 '{ 0 }': u64 | ||
393 | 160..161 '0': u64 | ||
394 | 174..196 '{ ...f(); }': () | ||
395 | 184..186 '_a': u64 | ||
396 | 190..191 'f': fn f() -> u64 | ||
397 | 190..193 'f()': u64 | ||
398 | "#]], | ||
399 | ); | ||
400 | } | ||
401 | |||
402 | #[test] | ||
403 | fn infer_local_macro() { | ||
404 | check_infer( | ||
405 | r#" | ||
406 | fn main() { | ||
407 | macro_rules! foo { | ||
408 | () => { 1usize } | ||
409 | } | ||
410 | let _a = foo!(); | ||
411 | } | ||
412 | "#, | ||
413 | expect![[r#" | ||
414 | !0..6 '1usize': usize | ||
415 | 10..89 '{ ...!(); }': () | ||
416 | 16..65 'macro_... }': {unknown} | ||
417 | 74..76 '_a': usize | ||
418 | "#]], | ||
419 | ); | ||
420 | } | ||
421 | |||
422 | #[test] | ||
423 | fn infer_local_inner_macros() { | ||
424 | check_types( | ||
425 | r#" | ||
426 | //- /main.rs crate:main deps:foo | ||
427 | fn test() { | ||
428 | let x = foo::foo!(1); | ||
429 | x; | ||
430 | } //^ i32 | ||
431 | |||
432 | //- /lib.rs crate:foo | ||
433 | #[macro_export(local_inner_macros)] | ||
434 | macro_rules! foo { | ||
435 | (1) => { bar!() }; | ||
436 | } | ||
437 | |||
438 | #[macro_export] | ||
439 | macro_rules! bar { | ||
440 | () => { 42 } | ||
441 | } | ||
442 | |||
443 | "#, | ||
444 | ); | ||
445 | } | ||
446 | |||
447 | #[test] | ||
448 | fn infer_builtin_macros_line() { | ||
449 | check_infer( | ||
450 | r#" | ||
451 | #[rustc_builtin_macro] | ||
452 | macro_rules! line {() => {}} | ||
453 | |||
454 | fn main() { | ||
455 | let x = line!(); | ||
456 | } | ||
457 | "#, | ||
458 | expect![[r#" | ||
459 | !0..1 '0': i32 | ||
460 | 63..87 '{ ...!(); }': () | ||
461 | 73..74 'x': i32 | ||
462 | "#]], | ||
463 | ); | ||
464 | } | ||
465 | |||
466 | #[test] | ||
467 | fn infer_builtin_macros_file() { | ||
468 | check_infer( | ||
469 | r#" | ||
470 | #[rustc_builtin_macro] | ||
471 | macro_rules! file {() => {}} | ||
472 | |||
473 | fn main() { | ||
474 | let x = file!(); | ||
475 | } | ||
476 | "#, | ||
477 | expect![[r#" | ||
478 | !0..2 '""': &str | ||
479 | 63..87 '{ ...!(); }': () | ||
480 | 73..74 'x': &str | ||
481 | "#]], | ||
482 | ); | ||
483 | } | ||
484 | |||
485 | #[test] | ||
486 | fn infer_builtin_macros_column() { | ||
487 | check_infer( | ||
488 | r#" | ||
489 | #[rustc_builtin_macro] | ||
490 | macro_rules! column {() => {}} | ||
491 | |||
492 | fn main() { | ||
493 | let x = column!(); | ||
494 | } | ||
495 | "#, | ||
496 | expect![[r#" | ||
497 | !0..1 '0': i32 | ||
498 | 65..91 '{ ...!(); }': () | ||
499 | 75..76 'x': i32 | ||
500 | "#]], | ||
501 | ); | ||
502 | } | ||
503 | |||
504 | #[test] | ||
505 | fn infer_builtin_macros_concat() { | ||
506 | check_infer( | ||
507 | r#" | ||
508 | #[rustc_builtin_macro] | ||
509 | macro_rules! concat {() => {}} | ||
510 | |||
511 | fn main() { | ||
512 | let x = concat!("hello", concat!("world", "!")); | ||
513 | } | ||
514 | "#, | ||
515 | expect![[r#" | ||
516 | !0..13 '"helloworld!"': &str | ||
517 | 65..121 '{ ...")); }': () | ||
518 | 75..76 'x': &str | ||
519 | "#]], | ||
520 | ); | ||
521 | } | ||
522 | |||
523 | #[test] | ||
524 | fn infer_builtin_macros_include() { | ||
525 | check_types( | ||
526 | r#" | ||
527 | //- /main.rs | ||
528 | #[rustc_builtin_macro] | ||
529 | macro_rules! include {() => {}} | ||
530 | |||
531 | include!("foo.rs"); | ||
532 | |||
533 | fn main() { | ||
534 | bar(); | ||
535 | } //^ u32 | ||
536 | |||
537 | //- /foo.rs | ||
538 | fn bar() -> u32 {0} | ||
539 | "#, | ||
540 | ); | ||
541 | } | ||
542 | |||
543 | #[test] | ||
544 | #[ignore] | ||
545 | fn include_accidentally_quadratic() { | ||
546 | let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic"); | ||
547 | let big_file = fs::read_to_string(file).unwrap(); | ||
548 | let big_file = vec![big_file; 10].join("\n"); | ||
549 | |||
550 | let fixture = r#" | ||
551 | //- /main.rs | ||
552 | #[rustc_builtin_macro] | ||
553 | macro_rules! include {() => {}} | ||
554 | |||
555 | include!("foo.rs"); | ||
556 | |||
557 | fn main() { | ||
558 | RegisterBlock { }; | ||
559 | //^ RegisterBlock | ||
560 | } | ||
561 | "#; | ||
562 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file); | ||
563 | check_types(&fixture); | ||
564 | } | ||
565 | |||
566 | #[test] | ||
567 | fn infer_builtin_macros_include_concat() { | ||
568 | check_types( | ||
569 | r#" | ||
570 | //- /main.rs | ||
571 | #[rustc_builtin_macro] | ||
572 | macro_rules! include {() => {}} | ||
573 | |||
574 | #[rustc_builtin_macro] | ||
575 | macro_rules! concat {() => {}} | ||
576 | |||
577 | include!(concat!("f", "oo.rs")); | ||
578 | |||
579 | fn main() { | ||
580 | bar(); | ||
581 | } //^ u32 | ||
582 | |||
583 | //- /foo.rs | ||
584 | fn bar() -> u32 {0} | ||
585 | "#, | ||
586 | ); | ||
587 | } | ||
588 | |||
589 | #[test] | ||
590 | fn infer_builtin_macros_include_concat_with_bad_env_should_failed() { | ||
591 | check_types( | ||
592 | r#" | ||
593 | //- /main.rs | ||
594 | #[rustc_builtin_macro] | ||
595 | macro_rules! include {() => {}} | ||
596 | |||
597 | #[rustc_builtin_macro] | ||
598 | macro_rules! concat {() => {}} | ||
599 | |||
600 | #[rustc_builtin_macro] | ||
601 | macro_rules! env {() => {}} | ||
602 | |||
603 | include!(concat!(env!("OUT_DIR"), "/foo.rs")); | ||
604 | |||
605 | fn main() { | ||
606 | bar(); | ||
607 | } //^ {unknown} | ||
608 | |||
609 | //- /foo.rs | ||
610 | fn bar() -> u32 {0} | ||
611 | "#, | ||
612 | ); | ||
613 | } | ||
614 | |||
615 | #[test] | ||
616 | fn infer_builtin_macros_include_itself_should_failed() { | ||
617 | check_types( | ||
618 | r#" | ||
619 | #[rustc_builtin_macro] | ||
620 | macro_rules! include {() => {}} | ||
621 | |||
622 | include!("main.rs"); | ||
623 | |||
624 | fn main() { | ||
625 | 0 | ||
626 | } //^ i32 | ||
627 | "#, | ||
628 | ); | ||
629 | } | ||
630 | |||
631 | #[test] | ||
632 | fn infer_builtin_macros_concat_with_lazy() { | ||
633 | check_infer( | ||
634 | r#" | ||
635 | macro_rules! hello {() => {"hello"}} | ||
636 | |||
637 | #[rustc_builtin_macro] | ||
638 | macro_rules! concat {() => {}} | ||
639 | |||
640 | fn main() { | ||
641 | let x = concat!(hello!(), concat!("world", "!")); | ||
642 | } | ||
643 | "#, | ||
644 | expect![[r#" | ||
645 | !0..13 '"helloworld!"': &str | ||
646 | 103..160 '{ ...")); }': () | ||
647 | 113..114 'x': &str | ||
648 | "#]], | ||
649 | ); | ||
650 | } | ||
651 | |||
652 | #[test] | ||
653 | fn infer_builtin_macros_env() { | ||
654 | check_infer( | ||
655 | r#" | ||
656 | //- /main.rs env:foo=bar | ||
657 | #[rustc_builtin_macro] | ||
658 | macro_rules! env {() => {}} | ||
659 | |||
660 | fn main() { | ||
661 | let x = env!("foo"); | ||
662 | } | ||
663 | "#, | ||
664 | expect![[r#" | ||
665 | !0..22 '"__RA_...TED__"': &str | ||
666 | 62..90 '{ ...o"); }': () | ||
667 | 72..73 'x': &str | ||
668 | "#]], | ||
669 | ); | ||
670 | } | ||
671 | |||
672 | #[test] | ||
673 | fn infer_derive_clone_simple() { | ||
674 | check_types( | ||
675 | r#" | ||
676 | //- /main.rs crate:main deps:core | ||
677 | #[derive(Clone)] | ||
678 | struct S; | ||
679 | fn test() { | ||
680 | S.clone(); | ||
681 | } //^ S | ||
682 | |||
683 | //- /lib.rs crate:core | ||
684 | #[prelude_import] | ||
685 | use clone::*; | ||
686 | mod clone { | ||
687 | trait Clone { | ||
688 | fn clone(&self) -> Self; | ||
689 | } | ||
690 | } | ||
691 | "#, | ||
692 | ); | ||
693 | } | ||
694 | |||
695 | #[test] | ||
696 | fn infer_derive_clone_in_core() { | ||
697 | check_types( | ||
698 | r#" | ||
699 | //- /lib.rs crate:core | ||
700 | #[prelude_import] | ||
701 | use clone::*; | ||
702 | mod clone { | ||
703 | trait Clone { | ||
704 | fn clone(&self) -> Self; | ||
705 | } | ||
706 | } | ||
707 | #[derive(Clone)] | ||
708 | pub struct S; | ||
709 | |||
710 | //- /main.rs crate:main deps:core | ||
711 | use core::S; | ||
712 | fn test() { | ||
713 | S.clone(); | ||
714 | } //^ S | ||
715 | "#, | ||
716 | ); | ||
717 | } | ||
718 | |||
719 | #[test] | ||
720 | fn infer_derive_clone_with_params() { | ||
721 | check_types( | ||
722 | r#" | ||
723 | //- /main.rs crate:main deps:core | ||
724 | #[derive(Clone)] | ||
725 | struct S; | ||
726 | #[derive(Clone)] | ||
727 | struct Wrapper<T>(T); | ||
728 | struct NonClone; | ||
729 | fn test() { | ||
730 | (Wrapper(S).clone(), Wrapper(NonClone).clone()); | ||
731 | //^ (Wrapper<S>, {unknown}) | ||
732 | } | ||
733 | |||
734 | //- /lib.rs crate:core | ||
735 | #[prelude_import] | ||
736 | use clone::*; | ||
737 | mod clone { | ||
738 | trait Clone { | ||
739 | fn clone(&self) -> Self; | ||
740 | } | ||
741 | } | ||
742 | "#, | ||
743 | ); | ||
744 | } | ||
745 | |||
746 | #[test] | ||
747 | fn infer_custom_derive_simple() { | ||
748 | // FIXME: this test current now do nothing | ||
749 | check_types( | ||
750 | r#" | ||
751 | //- /main.rs crate:main | ||
752 | use foo::Foo; | ||
753 | |||
754 | #[derive(Foo)] | ||
755 | struct S{} | ||
756 | |||
757 | fn test() { | ||
758 | S{}; | ||
759 | } //^ S | ||
760 | "#, | ||
761 | ); | ||
762 | } | ||
763 | |||
764 | #[test] | ||
765 | fn macro_in_arm() { | ||
766 | check_infer( | ||
767 | r#" | ||
768 | macro_rules! unit { | ||
769 | () => { () }; | ||
770 | } | ||
771 | |||
772 | fn main() { | ||
773 | let x = match () { | ||
774 | unit!() => 92u32, | ||
775 | }; | ||
776 | } | ||
777 | "#, | ||
778 | expect![[r#" | ||
779 | 51..110 '{ ... }; }': () | ||
780 | 61..62 'x': u32 | ||
781 | 65..107 'match ... }': u32 | ||
782 | 71..73 '()': () | ||
783 | 84..91 'unit!()': () | ||
784 | 95..100 '92u32': u32 | ||
785 | "#]], | ||
786 | ); | ||
787 | } | ||