]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-ty / src / tests / patterns.rs
1 use expect_test::expect;
2
3 use super::{check, check_infer, check_infer_with_mismatches, check_types};
4
5 #[test]
6 fn infer_pattern() {
7 check_infer(
8 r#"
9 fn test(x: &i32) {
10 let y = x;
11 let &z = x;
12 let a = z;
13 let (c, d) = (1, "hello");
14
15 for (e, f) in some_iter {
16 let g = e;
17 }
18
19 if let [val] = opt {
20 let h = val;
21 }
22
23 if let x @ true = &true {}
24
25 let lambda = |a: u64, b, c: i32| { a + b; c };
26
27 let ref ref_to_x = x;
28 let mut mut_x = x;
29 let ref mut mut_ref_to_x = x;
30 let k = mut_ref_to_x;
31 }
32 "#,
33 expect![[r#"
34 8..9 'x': &i32
35 17..400 '{ ...o_x; }': ()
36 27..28 'y': &i32
37 31..32 'x': &i32
38 42..44 '&z': &i32
39 43..44 'z': i32
40 47..48 'x': &i32
41 58..59 'a': i32
42 62..63 'z': i32
43 73..79 '(c, d)': (i32, &str)
44 74..75 'c': i32
45 77..78 'd': &str
46 82..94 '(1, "hello")': (i32, &str)
47 83..84 '1': i32
48 86..93 '"hello"': &str
49 101..151 'for (e... }': ()
50 105..111 '(e, f)': ({unknown}, {unknown})
51 106..107 'e': {unknown}
52 109..110 'f': {unknown}
53 115..124 'some_iter': {unknown}
54 125..151 '{ ... }': ()
55 139..140 'g': {unknown}
56 143..144 'e': {unknown}
57 157..204 'if let... }': ()
58 160..175 'let [val] = opt': bool
59 164..169 '[val]': [{unknown}]
60 165..168 'val': {unknown}
61 172..175 'opt': [{unknown}]
62 176..204 '{ ... }': ()
63 190..191 'h': {unknown}
64 194..197 'val': {unknown}
65 210..236 'if let...rue {}': ()
66 213..233 'let x ... &true': bool
67 217..225 'x @ true': &bool
68 221..225 'true': bool
69 221..225 'true': bool
70 228..233 '&true': &bool
71 229..233 'true': bool
72 234..236 '{}': ()
73 246..252 'lambda': |u64, u64, i32| -> i32
74 255..287 '|a: u6...b; c }': |u64, u64, i32| -> i32
75 256..257 'a': u64
76 264..265 'b': u64
77 267..268 'c': i32
78 275..287 '{ a + b; c }': i32
79 277..278 'a': u64
80 277..282 'a + b': u64
81 281..282 'b': u64
82 284..285 'c': i32
83 298..310 'ref ref_to_x': &&i32
84 313..314 'x': &i32
85 324..333 'mut mut_x': &i32
86 336..337 'x': &i32
87 347..367 'ref mu...f_to_x': &mut &i32
88 370..371 'x': &i32
89 381..382 'k': &mut &i32
90 385..397 'mut_ref_to_x': &mut &i32
91 "#]],
92 );
93 }
94
95 #[test]
96 fn infer_literal_pattern() {
97 check_infer_with_mismatches(
98 r#"
99 fn any<T>() -> T { loop {} }
100 fn test(x: &i32) {
101 if let "foo" = any() {}
102 if let 1 = any() {}
103 if let 1u32 = any() {}
104 if let 1f32 = any() {}
105 if let 1.0 = any() {}
106 if let true = any() {}
107 }
108 "#,
109 expect![[r#"
110 17..28 '{ loop {} }': T
111 19..26 'loop {}': !
112 24..26 '{}': ()
113 37..38 'x': &i32
114 46..208 '{ ...) {} }': ()
115 52..75 'if let...y() {}': ()
116 55..72 'let "f... any()': bool
117 59..64 '"foo"': &str
118 59..64 '"foo"': &str
119 67..70 'any': fn any<&str>() -> &str
120 67..72 'any()': &str
121 73..75 '{}': ()
122 80..99 'if let...y() {}': ()
123 83..96 'let 1 = any()': bool
124 87..88 '1': i32
125 87..88 '1': i32
126 91..94 'any': fn any<i32>() -> i32
127 91..96 'any()': i32
128 97..99 '{}': ()
129 104..126 'if let...y() {}': ()
130 107..123 'let 1u... any()': bool
131 111..115 '1u32': u32
132 111..115 '1u32': u32
133 118..121 'any': fn any<u32>() -> u32
134 118..123 'any()': u32
135 124..126 '{}': ()
136 131..153 'if let...y() {}': ()
137 134..150 'let 1f... any()': bool
138 138..142 '1f32': f32
139 138..142 '1f32': f32
140 145..148 'any': fn any<f32>() -> f32
141 145..150 'any()': f32
142 151..153 '{}': ()
143 158..179 'if let...y() {}': ()
144 161..176 'let 1.0 = any()': bool
145 165..168 '1.0': f64
146 165..168 '1.0': f64
147 171..174 'any': fn any<f64>() -> f64
148 171..176 'any()': f64
149 177..179 '{}': ()
150 184..206 'if let...y() {}': ()
151 187..203 'let tr... any()': bool
152 191..195 'true': bool
153 191..195 'true': bool
154 198..201 'any': fn any<bool>() -> bool
155 198..203 'any()': bool
156 204..206 '{}': ()
157 "#]],
158 );
159 }
160
161 #[test]
162 fn infer_range_pattern() {
163 check_infer_with_mismatches(
164 r#"
165 fn test(x: &i32) {
166 if let 1..76 = 2u32 {}
167 if let 1..=76 = 2u32 {}
168 }
169 "#,
170 expect![[r#"
171 8..9 'x': &i32
172 17..75 '{ ...2 {} }': ()
173 23..45 'if let...u32 {}': ()
174 26..42 'let 1....= 2u32': bool
175 30..35 '1..76': u32
176 38..42 '2u32': u32
177 43..45 '{}': ()
178 50..73 'if let...u32 {}': ()
179 53..70 'let 1....= 2u32': bool
180 57..63 '1..=76': u32
181 66..70 '2u32': u32
182 71..73 '{}': ()
183 "#]],
184 );
185 }
186
187 #[test]
188 fn infer_pattern_match_ergonomics() {
189 check_infer(
190 r#"
191 struct A<T>(T);
192
193 fn test() {
194 let A(n) = &A(1);
195 let A(n) = &mut A(1);
196 }
197 "#,
198 expect![[r#"
199 27..78 '{ ...(1); }': ()
200 37..41 'A(n)': A<i32>
201 39..40 'n': &i32
202 44..49 '&A(1)': &A<i32>
203 45..46 'A': A<i32>(i32) -> A<i32>
204 45..49 'A(1)': A<i32>
205 47..48 '1': i32
206 59..63 'A(n)': A<i32>
207 61..62 'n': &mut i32
208 66..75 '&mut A(1)': &mut A<i32>
209 71..72 'A': A<i32>(i32) -> A<i32>
210 71..75 'A(1)': A<i32>
211 73..74 '1': i32
212 "#]],
213 );
214 }
215
216 #[test]
217 fn infer_pattern_match_ergonomics_ref() {
218 cov_mark::check!(match_ergonomics_ref);
219 check_infer(
220 r#"
221 fn test() {
222 let v = &(1, &2);
223 let (_, &w) = v;
224 }
225 "#,
226 expect![[r#"
227 10..56 '{ ...= v; }': ()
228 20..21 'v': &(i32, &i32)
229 24..32 '&(1, &2)': &(i32, &i32)
230 25..32 '(1, &2)': (i32, &i32)
231 26..27 '1': i32
232 29..31 '&2': &i32
233 30..31 '2': i32
234 42..49 '(_, &w)': (i32, &i32)
235 43..44 '_': i32
236 46..48 '&w': &i32
237 47..48 'w': i32
238 52..53 'v': &(i32, &i32)
239 "#]],
240 );
241 }
242
243 #[test]
244 fn infer_pattern_match_slice() {
245 check_infer(
246 r#"
247 fn test() {
248 let slice: &[f64] = &[0.0];
249 match slice {
250 &[] => {},
251 &[a] => {
252 a;
253 },
254 &[b, c] => {
255 b;
256 c;
257 }
258 _ => {}
259 }
260 }
261 "#,
262 expect![[r#"
263 10..209 '{ ... } }': ()
264 20..25 'slice': &[f64]
265 36..42 '&[0.0]': &[f64; 1]
266 37..42 '[0.0]': [f64; 1]
267 38..41 '0.0': f64
268 48..207 'match ... }': ()
269 54..59 'slice': &[f64]
270 70..73 '&[]': &[f64]
271 71..73 '[]': [f64]
272 77..79 '{}': ()
273 89..93 '&[a]': &[f64]
274 90..93 '[a]': [f64]
275 91..92 'a': f64
276 97..123 '{ ... }': ()
277 111..112 'a': f64
278 133..140 '&[b, c]': &[f64]
279 134..140 '[b, c]': [f64]
280 135..136 'b': f64
281 138..139 'c': f64
282 144..185 '{ ... }': ()
283 158..159 'b': f64
284 173..174 'c': f64
285 194..195 '_': &[f64]
286 199..201 '{}': ()
287 "#]],
288 );
289 }
290
291 #[test]
292 fn infer_pattern_match_string_literal() {
293 check_infer_with_mismatches(
294 r#"
295 fn test() {
296 let s: &str = "hello";
297 match s {
298 "hello" => {}
299 _ => {}
300 }
301 }
302 "#,
303 expect![[r#"
304 10..98 '{ ... } }': ()
305 20..21 's': &str
306 30..37 '"hello"': &str
307 43..96 'match ... }': ()
308 49..50 's': &str
309 61..68 '"hello"': &str
310 61..68 '"hello"': &str
311 72..74 '{}': ()
312 83..84 '_': &str
313 88..90 '{}': ()
314 "#]],
315 );
316 }
317
318 #[test]
319 fn infer_pattern_match_byte_string_literal() {
320 check_infer_with_mismatches(
321 r#"
322 //- minicore: index
323 struct S;
324 impl<T, const N: usize> core::ops::Index<S> for [T; N] {
325 type Output = [u8];
326 fn index(&self, index: core::ops::RangeFull) -> &Self::Output {
327 loop {}
328 }
329 }
330 fn test(v: [u8; 3]) {
331 if let b"foo" = &v[S] {}
332 if let b"foo" = &v {}
333 }
334 "#,
335 expect![[r#"
336 105..109 'self': &[T; N]
337 111..116 'index': {unknown}
338 157..180 '{ ... }': &[u8]
339 167..174 'loop {}': !
340 172..174 '{}': ()
341 191..192 'v': [u8; 3]
342 203..261 '{ ...v {} }': ()
343 209..233 'if let...[S] {}': ()
344 212..230 'let b"... &v[S]': bool
345 216..222 'b"foo"': &[u8]
346 216..222 'b"foo"': &[u8]
347 225..230 '&v[S]': &[u8]
348 226..227 'v': [u8; 3]
349 226..230 'v[S]': [u8]
350 228..229 'S': S
351 231..233 '{}': ()
352 238..259 'if let... &v {}': ()
353 241..256 'let b"foo" = &v': bool
354 245..251 'b"foo"': &[u8; 3]
355 245..251 'b"foo"': &[u8; 3]
356 254..256 '&v': &[u8; 3]
357 255..256 'v': [u8; 3]
358 257..259 '{}': ()
359 "#]],
360 );
361 }
362
363 #[test]
364 fn infer_pattern_match_or() {
365 check_infer_with_mismatches(
366 r#"
367 fn test() {
368 let s: &str = "hello";
369 match s {
370 "hello" | "world" => {}
371 _ => {}
372 }
373 }
374 "#,
375 expect![[r#"
376 10..108 '{ ... } }': ()
377 20..21 's': &str
378 30..37 '"hello"': &str
379 43..106 'match ... }': ()
380 49..50 's': &str
381 61..68 '"hello"': &str
382 61..68 '"hello"': &str
383 61..78 '"hello...world"': &str
384 71..78 '"world"': &str
385 71..78 '"world"': &str
386 82..84 '{}': ()
387 93..94 '_': &str
388 98..100 '{}': ()
389 "#]],
390 );
391 }
392
393 #[test]
394 fn infer_pattern_match_arr() {
395 check_infer(
396 r#"
397 fn test() {
398 let arr: [f64; 2] = [0.0, 1.0];
399 match arr {
400 [1.0, a] => {
401 a;
402 },
403 [b, c] => {
404 b;
405 c;
406 }
407 }
408 }
409 "#,
410 expect![[r#"
411 10..179 '{ ... } }': ()
412 20..23 'arr': [f64; 2]
413 36..46 '[0.0, 1.0]': [f64; 2]
414 37..40 '0.0': f64
415 42..45 '1.0': f64
416 52..177 'match ... }': ()
417 58..61 'arr': [f64; 2]
418 72..80 '[1.0, a]': [f64; 2]
419 73..76 '1.0': f64
420 73..76 '1.0': f64
421 78..79 'a': f64
422 84..110 '{ ... }': ()
423 98..99 'a': f64
424 120..126 '[b, c]': [f64; 2]
425 121..122 'b': f64
426 124..125 'c': f64
427 130..171 '{ ... }': ()
428 144..145 'b': f64
429 159..160 'c': f64
430 "#]],
431 );
432 }
433
434 #[test]
435 fn infer_adt_pattern() {
436 check_infer(
437 r#"
438 enum E {
439 A { x: usize },
440 B
441 }
442
443 struct S(u32, E);
444
445 fn test() {
446 let e = E::A { x: 3 };
447
448 let S(y, z) = foo;
449 let E::A { x: new_var } = e;
450
451 match e {
452 E::A { x } => x,
453 E::B if foo => 1,
454 E::B => 10,
455 };
456
457 let ref d @ E::A { .. } = e;
458 d;
459 }
460 "#,
461 expect![[r#"
462 67..288 '{ ... d; }': ()
463 77..78 'e': E
464 81..94 'E::A { x: 3 }': E
465 91..92 '3': usize
466 105..112 'S(y, z)': S
467 107..108 'y': u32
468 110..111 'z': E
469 115..118 'foo': S
470 128..147 'E::A {..._var }': E
471 138..145 'new_var': usize
472 150..151 'e': E
473 158..244 'match ... }': usize
474 164..165 'e': E
475 176..186 'E::A { x }': E
476 183..184 'x': usize
477 190..191 'x': usize
478 201..205 'E::B': E
479 209..212 'foo': bool
480 216..217 '1': usize
481 227..231 'E::B': E
482 235..237 '10': usize
483 255..274 'ref d ...{ .. }': &E
484 263..274 'E::A { .. }': E
485 277..278 'e': E
486 284..285 'd': &E
487 "#]],
488 );
489 }
490
491 #[test]
492 fn tuple_struct_destructured_with_self() {
493 check_infer(
494 r#"
495 struct Foo(usize,);
496 impl Foo {
497 fn f() {
498 let Self(s,) = &Foo(0,);
499 let Self(s,) = &mut Foo(0,);
500 let Self(s,) = Foo(0,);
501 }
502 }
503 "#,
504 expect![[r#"
505 42..151 '{ ... }': ()
506 56..64 'Self(s,)': Foo
507 61..62 's': &usize
508 67..75 '&Foo(0,)': &Foo
509 68..71 'Foo': Foo(usize) -> Foo
510 68..75 'Foo(0,)': Foo
511 72..73 '0': usize
512 89..97 'Self(s,)': Foo
513 94..95 's': &mut usize
514 100..112 '&mut Foo(0,)': &mut Foo
515 105..108 'Foo': Foo(usize) -> Foo
516 105..112 'Foo(0,)': Foo
517 109..110 '0': usize
518 126..134 'Self(s,)': Foo
519 131..132 's': usize
520 137..140 'Foo': Foo(usize) -> Foo
521 137..144 'Foo(0,)': Foo
522 141..142 '0': usize
523 "#]],
524 );
525 }
526
527 #[test]
528 fn enum_variant_through_self_in_pattern() {
529 check_infer(
530 r#"
531 enum E {
532 A { x: usize },
533 B(usize),
534 C
535 }
536
537 impl E {
538 fn test() {
539 match (loop {}) {
540 Self::A { x } => { x; },
541 Self::B(x) => { x; },
542 Self::C => {},
543 };
544 }
545 }
546 "#,
547 expect![[r#"
548 75..217 '{ ... }': ()
549 85..210 'match ... }': ()
550 92..99 'loop {}': !
551 97..99 '{}': ()
552 115..128 'Self::A { x }': E
553 125..126 'x': usize
554 132..138 '{ x; }': ()
555 134..135 'x': usize
556 152..162 'Self::B(x)': E
557 160..161 'x': usize
558 166..172 '{ x; }': ()
559 168..169 'x': usize
560 186..193 'Self::C': E
561 197..199 '{}': ()
562 "#]],
563 );
564 }
565
566 #[test]
567 fn infer_generics_in_patterns() {
568 check_infer(
569 r#"
570 struct A<T> {
571 x: T,
572 }
573
574 enum Option<T> {
575 Some(T),
576 None,
577 }
578
579 fn test(a1: A<u32>, o: Option<u64>) {
580 let A { x: x2 } = a1;
581 let A::<i64> { x: x3 } = A { x: 1 };
582 match o {
583 Option::Some(t) => t,
584 _ => 1,
585 };
586 }
587 "#,
588 expect![[r#"
589 78..80 'a1': A<u32>
590 90..91 'o': Option<u64>
591 106..243 '{ ... }; }': ()
592 116..127 'A { x: x2 }': A<u32>
593 123..125 'x2': u32
594 130..132 'a1': A<u32>
595 142..160 'A::<i6...: x3 }': A<i64>
596 156..158 'x3': i64
597 163..173 'A { x: 1 }': A<i64>
598 170..171 '1': i64
599 179..240 'match ... }': u64
600 185..186 'o': Option<u64>
601 197..212 'Option::Some(t)': Option<u64>
602 210..211 't': u64
603 216..217 't': u64
604 227..228 '_': Option<u64>
605 232..233 '1': u64
606 "#]],
607 );
608 }
609
610 #[test]
611 fn infer_const_pattern() {
612 check(
613 r#"
614 enum Option<T> { None }
615 use Option::None;
616 struct Foo;
617 const Bar: usize = 1;
618
619 fn test() {
620 let a: Option<u32> = None;
621 let b: Option<i64> = match a {
622 None => None,
623 };
624 let _: () = match () { Foo => () };
625 // ^^^ expected (), got Foo
626 let _: () = match () { Bar => () };
627 // ^^^ expected (), got usize
628 }
629 "#,
630 );
631 }
632
633 #[test]
634 fn infer_guard() {
635 check_infer(
636 r#"
637 struct S;
638 impl S { fn foo(&self) -> bool { false } }
639
640 fn main() {
641 match S {
642 s if s.foo() => (),
643 }
644 }
645 "#,
646 expect![[r#"
647 27..31 'self': &S
648 41..50 '{ false }': bool
649 43..48 'false': bool
650 64..115 '{ ... } }': ()
651 70..113 'match ... }': ()
652 76..77 'S': S
653 88..89 's': S
654 93..94 's': S
655 93..100 's.foo()': bool
656 104..106 '()': ()
657 "#]],
658 )
659 }
660
661 #[test]
662 fn match_ergonomics_in_closure_params() {
663 check_infer(
664 r#"
665 //- minicore: fn
666 fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} }
667
668 fn test() {
669 foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics
670 foo(&(1, "a"), |(x, y)| x);
671 }
672 "#,
673 expect![[r#"
674 32..33 't': T
675 38..39 'f': F
676 49..60 '{ loop {} }': U
677 51..58 'loop {}': !
678 56..58 '{}': ()
679 72..171 '{ ... x); }': ()
680 78..81 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32
681 78..105 'foo(&(...y)| x)': i32
682 82..91 '&(1, "a")': &(i32, &str)
683 83..91 '(1, "a")': (i32, &str)
684 84..85 '1': i32
685 87..90 '"a"': &str
686 93..104 '|&(x, y)| x': |&(i32, &str)| -> i32
687 94..101 '&(x, y)': &(i32, &str)
688 95..101 '(x, y)': (i32, &str)
689 96..97 'x': i32
690 99..100 'y': &str
691 103..104 'x': i32
692 142..145 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32
693 142..168 'foo(&(...y)| x)': &i32
694 146..155 '&(1, "a")': &(i32, &str)
695 147..155 '(1, "a")': (i32, &str)
696 148..149 '1': i32
697 151..154 '"a"': &str
698 157..167 '|(x, y)| x': |&(i32, &str)| -> &i32
699 158..164 '(x, y)': (i32, &str)
700 159..160 'x': &i32
701 162..163 'y': &&str
702 166..167 'x': &i32
703 "#]],
704 );
705 }
706
707 #[test]
708 fn slice_tail_pattern() {
709 check_infer(
710 r#"
711 fn foo(params: &[i32]) {
712 match params {
713 [head, tail @ ..] => {
714 }
715 }
716 }
717 "#,
718 expect![[r#"
719 7..13 'params': &[i32]
720 23..92 '{ ... } }': ()
721 29..90 'match ... }': ()
722 35..41 'params': &[i32]
723 52..69 '[head,... @ ..]': [i32]
724 53..57 'head': &i32
725 59..68 'tail @ ..': &[i32]
726 66..68 '..': [i32]
727 73..84 '{ }': ()
728 "#]],
729 );
730 }
731
732 #[test]
733 fn box_pattern() {
734 check_infer(
735 r#"
736 pub struct Global;
737 #[lang = "owned_box"]
738 pub struct Box<T, A = Global>(T);
739
740 fn foo(params: Box<i32>) {
741 match params {
742 box integer => {}
743 }
744 }
745 "#,
746 expect![[r#"
747 83..89 'params': Box<i32, Global>
748 101..155 '{ ... } }': ()
749 107..153 'match ... }': ()
750 113..119 'params': Box<i32, Global>
751 130..141 'box integer': Box<i32, Global>
752 134..141 'integer': i32
753 145..147 '{}': ()
754 "#]],
755 );
756 check_infer(
757 r#"
758 #[lang = "owned_box"]
759 pub struct Box<T>(T);
760
761 fn foo(params: Box<i32>) {
762 match params {
763 box integer => {}
764 }
765 }
766 "#,
767 expect![[r#"
768 52..58 'params': Box<i32>
769 70..124 '{ ... } }': ()
770 76..122 'match ... }': ()
771 82..88 'params': Box<i32>
772 99..110 'box integer': Box<i32>
773 103..110 'integer': i32
774 114..116 '{}': ()
775 "#]],
776 );
777 }
778
779 #[test]
780 fn tuple_ellipsis_pattern() {
781 check_infer_with_mismatches(
782 r#"
783 fn foo(tuple: (u8, i16, f32)) {
784 match tuple {
785 (.., b, c) => {},
786 (a, .., c) => {},
787 (a, b, ..) => {},
788 (a, b) => {/*too short*/}
789 (a, b, c, d) => {/*too long*/}
790 _ => {}
791 }
792 }"#,
793 expect![[r#"
794 7..12 'tuple': (u8, i16, f32)
795 30..224 '{ ... } }': ()
796 36..222 'match ... }': ()
797 42..47 'tuple': (u8, i16, f32)
798 58..68 '(.., b, c)': (u8, i16, f32)
799 63..64 'b': i16
800 66..67 'c': f32
801 72..74 '{}': ()
802 84..94 '(a, .., c)': (u8, i16, f32)
803 85..86 'a': u8
804 92..93 'c': f32
805 98..100 '{}': ()
806 110..120 '(a, b, ..)': (u8, i16, f32)
807 111..112 'a': u8
808 114..115 'b': i16
809 124..126 '{}': ()
810 136..142 '(a, b)': (u8, i16)
811 137..138 'a': u8
812 140..141 'b': i16
813 146..161 '{/*too short*/}': ()
814 170..182 '(a, b, c, d)': (u8, i16, f32, {unknown})
815 171..172 'a': u8
816 174..175 'b': i16
817 177..178 'c': f32
818 180..181 'd': {unknown}
819 186..200 '{/*too long*/}': ()
820 209..210 '_': (u8, i16, f32)
821 214..216 '{}': ()
822 136..142: expected (u8, i16, f32), got (u8, i16)
823 170..182: expected (u8, i16, f32), got (u8, i16, f32, {unknown})
824 "#]],
825 );
826 }
827
828 #[test]
829 fn tuple_struct_ellipsis_pattern() {
830 check_infer(
831 r#"
832 struct Tuple(u8, i16, f32);
833 fn foo(tuple: Tuple) {
834 match tuple {
835 Tuple(.., b, c) => {},
836 Tuple(a, .., c) => {},
837 Tuple(a, b, ..) => {},
838 Tuple(a, b) => {/*too short*/}
839 Tuple(a, b, c, d) => {/*too long*/}
840 _ => {}
841 }
842 }"#,
843 expect![[r#"
844 35..40 'tuple': Tuple
845 49..268 '{ ... } }': ()
846 55..266 'match ... }': ()
847 61..66 'tuple': Tuple
848 77..92 'Tuple(.., b, c)': Tuple
849 87..88 'b': i16
850 90..91 'c': f32
851 96..98 '{}': ()
852 108..123 'Tuple(a, .., c)': Tuple
853 114..115 'a': u8
854 121..122 'c': f32
855 127..129 '{}': ()
856 139..154 'Tuple(a, b, ..)': Tuple
857 145..146 'a': u8
858 148..149 'b': i16
859 158..160 '{}': ()
860 170..181 'Tuple(a, b)': Tuple
861 176..177 'a': u8
862 179..180 'b': i16
863 185..200 '{/*too short*/}': ()
864 209..226 'Tuple(... c, d)': Tuple
865 215..216 'a': u8
866 218..219 'b': i16
867 221..222 'c': f32
868 224..225 'd': {unknown}
869 230..244 '{/*too long*/}': ()
870 253..254 '_': Tuple
871 258..260 '{}': ()
872 "#]],
873 );
874 }
875
876 #[test]
877 fn const_block_pattern() {
878 check_infer(
879 r#"
880 struct Foo(usize);
881 fn foo(foo: Foo) {
882 match foo {
883 const { Foo(15 + 32) } => {},
884 _ => {}
885 }
886 }"#,
887 expect![[r#"
888 26..29 'foo': Foo
889 36..115 '{ ... } }': ()
890 42..113 'match ... }': ()
891 48..51 'foo': Foo
892 62..84 'const ... 32) }': Foo
893 68..84 '{ Foo(... 32) }': Foo
894 70..73 'Foo': Foo(usize) -> Foo
895 70..82 'Foo(15 + 32)': Foo
896 74..76 '15': usize
897 74..81 '15 + 32': usize
898 79..81 '32': usize
899 88..90 '{}': ()
900 100..101 '_': Foo
901 105..107 '{}': ()
902 "#]],
903 );
904 }
905
906 #[test]
907 fn macro_pat() {
908 check_types(
909 r#"
910 macro_rules! pat {
911 ($name:ident) => { Enum::Variant1($name) }
912 }
913
914 enum Enum {
915 Variant1(u8),
916 Variant2,
917 }
918
919 fn f(e: Enum) {
920 match e {
921 pat!(bind) => {
922 bind;
923 //^^^^ u8
924 }
925 Enum::Variant2 => {}
926 }
927 }
928 "#,
929 )
930 }
931
932 #[test]
933 fn type_mismatch_in_or_pattern() {
934 check_infer_with_mismatches(
935 r#"
936 fn main() {
937 match (false,) {
938 (true | (),) => {}
939 (() | true,) => {}
940 (_ | (),) => {}
941 (() | _,) => {}
942 }
943 }
944 "#,
945 expect![[r#"
946 10..142 '{ ... } }': ()
947 16..140 'match ... }': ()
948 22..30 '(false,)': (bool,)
949 23..28 'false': bool
950 41..53 '(true | (),)': (bool,)
951 42..46 'true': bool
952 42..46 'true': bool
953 42..51 'true | ()': bool
954 49..51 '()': ()
955 57..59 '{}': ()
956 68..80 '(() | true,)': ((),)
957 69..71 '()': ()
958 69..78 '() | true': ()
959 74..78 'true': bool
960 74..78 'true': bool
961 84..86 '{}': ()
962 95..104 '(_ | (),)': (bool,)
963 96..97 '_': bool
964 96..102 '_ | ()': bool
965 100..102 '()': ()
966 108..110 '{}': ()
967 119..128 '(() | _,)': ((),)
968 120..122 '()': ()
969 120..126 '() | _': ()
970 125..126 '_': bool
971 132..134 '{}': ()
972 49..51: expected bool, got ()
973 68..80: expected (bool,), got ((),)
974 69..71: expected bool, got ()
975 69..78: expected bool, got ()
976 100..102: expected bool, got ()
977 119..128: expected (bool,), got ((),)
978 120..122: expected bool, got ()
979 120..126: expected bool, got ()
980 "#]],
981 );
982 }
983
984 #[test]
985 fn slice_pattern_correctly_handles_array_length() {
986 check_infer(
987 r#"
988 fn main() {
989 let [head, middle @ .., tail, tail2] = [1, 2, 3, 4, 5];
990 }
991 "#,
992 expect![[r#"
993 10..73 '{ ... 5]; }': ()
994 20..52 '[head,...tail2]': [i32; 5]
995 21..25 'head': i32
996 27..38 'middle @ ..': [i32; 2]
997 36..38 '..': [i32; 2]
998 40..44 'tail': i32
999 46..51 'tail2': i32
1000 55..70 '[1, 2, 3, 4, 5]': [i32; 5]
1001 56..57 '1': i32
1002 59..60 '2': i32
1003 62..63 '3': i32
1004 65..66 '4': i32
1005 68..69 '5': i32
1006 "#]],
1007 );
1008 }
1009
1010 #[test]
1011 fn pattern_lookup_in_value_ns() {
1012 check_types(
1013 r#"
1014 use self::Constructor::*;
1015 struct IntRange {
1016 range: (),
1017 }
1018 enum Constructor {
1019 IntRange(IntRange),
1020 }
1021 fn main() {
1022 match Constructor::IntRange(IntRange { range: () }) {
1023 IntRange(x) => {
1024 x;
1025 //^ IntRange
1026 }
1027 Constructor::IntRange(x) => {
1028 x;
1029 //^ IntRange
1030 }
1031 }
1032 }
1033 "#,
1034 );
1035 }
1036
1037 #[test]
1038 fn if_let_guards() {
1039 check_types(
1040 r#"
1041 fn main() {
1042 match (0,) {
1043 opt if let (x,) = opt => {
1044 x;
1045 //^ i32
1046 }
1047 _ => {}
1048 }
1049 }
1050 "#,
1051 );
1052 }
1053
1054 #[test]
1055 fn tuple_wildcard() {
1056 check_types(
1057 r#"
1058 fn main() {
1059 enum Option<T> {Some(T), None}
1060 use Option::*;
1061
1062 let mut x = None;
1063 x;
1064 //^ Option<(i32, i32)>
1065
1066 if let Some((_, _a)) = x {}
1067
1068 x = Some((1, 2));
1069 }
1070 "#,
1071 );
1072 }
1073
1074 #[test]
1075 fn cfg_params() {
1076 check_types(
1077 r#"
1078 fn my_fn(#[cfg(feature = "feature")] u8: u8, u32: u32) {}
1079 //^^^ u32
1080 "#,
1081 );
1082 }