aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/tests/patterns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/tests/patterns.rs')
-rw-r--r--crates/hir_ty/src/tests/patterns.rs656
1 files changed, 656 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
new file mode 100644
index 000000000..39fabf7eb
--- /dev/null
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -0,0 +1,656 @@
1use expect::expect;
2use test_utils::mark;
3
4use super::{check_infer, check_infer_with_mismatches};
5
6#[test]
7fn infer_pattern() {
8 check_infer(
9 r#"
10 fn test(x: &i32) {
11 let y = x;
12 let &z = x;
13 let a = z;
14 let (c, d) = (1, "hello");
15
16 for (e, f) in some_iter {
17 let g = e;
18 }
19
20 if let [val] = opt {
21 let h = val;
22 }
23
24 let lambda = |a: u64, b, c: i32| { a + b; c };
25
26 let ref ref_to_x = x;
27 let mut mut_x = x;
28 let ref mut mut_ref_to_x = x;
29 let k = mut_ref_to_x;
30 }
31 "#,
32 expect![[r#"
33 8..9 'x': &i32
34 17..368 '{ ...o_x; }': ()
35 27..28 'y': &i32
36 31..32 'x': &i32
37 42..44 '&z': &i32
38 43..44 'z': i32
39 47..48 'x': &i32
40 58..59 'a': i32
41 62..63 'z': i32
42 73..79 '(c, d)': (i32, &str)
43 74..75 'c': i32
44 77..78 'd': &str
45 82..94 '(1, "hello")': (i32, &str)
46 83..84 '1': i32
47 86..93 '"hello"': &str
48 101..151 'for (e... }': ()
49 105..111 '(e, f)': ({unknown}, {unknown})
50 106..107 'e': {unknown}
51 109..110 'f': {unknown}
52 115..124 'some_iter': {unknown}
53 125..151 '{ ... }': ()
54 139..140 'g': {unknown}
55 143..144 'e': {unknown}
56 157..204 'if let... }': ()
57 164..169 '[val]': [{unknown}]
58 165..168 'val': {unknown}
59 172..175 'opt': [{unknown}]
60 176..204 '{ ... }': ()
61 190..191 'h': {unknown}
62 194..197 'val': {unknown}
63 214..220 'lambda': |u64, u64, i32| -> i32
64 223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32
65 224..225 'a': u64
66 232..233 'b': u64
67 235..236 'c': i32
68 243..255 '{ a + b; c }': i32
69 245..246 'a': u64
70 245..250 'a + b': u64
71 249..250 'b': u64
72 252..253 'c': i32
73 266..278 'ref ref_to_x': &&i32
74 281..282 'x': &i32
75 292..301 'mut mut_x': &i32
76 304..305 'x': &i32
77 315..335 'ref mu...f_to_x': &mut &i32
78 338..339 'x': &i32
79 349..350 'k': &mut &i32
80 353..365 'mut_ref_to_x': &mut &i32
81 "#]],
82 );
83}
84
85#[test]
86fn infer_literal_pattern() {
87 check_infer_with_mismatches(
88 r#"
89 fn any<T>() -> T { loop {} }
90 fn test(x: &i32) {
91 if let "foo" = any() {}
92 if let 1 = any() {}
93 if let 1u32 = any() {}
94 if let 1f32 = any() {}
95 if let 1.0 = any() {}
96 if let true = any() {}
97 }
98 "#,
99 expect![[r#"
100 17..28 '{ loop {} }': T
101 19..26 'loop {}': !
102 24..26 '{}': ()
103 37..38 'x': &i32
104 46..208 '{ ...) {} }': ()
105 52..75 'if let...y() {}': ()
106 59..64 '"foo"': &str
107 59..64 '"foo"': &str
108 67..70 'any': fn any<&str>() -> &str
109 67..72 'any()': &str
110 73..75 '{}': ()
111 80..99 'if let...y() {}': ()
112 87..88 '1': i32
113 87..88 '1': i32
114 91..94 'any': fn any<i32>() -> i32
115 91..96 'any()': i32
116 97..99 '{}': ()
117 104..126 'if let...y() {}': ()
118 111..115 '1u32': u32
119 111..115 '1u32': u32
120 118..121 'any': fn any<u32>() -> u32
121 118..123 'any()': u32
122 124..126 '{}': ()
123 131..153 'if let...y() {}': ()
124 138..142 '1f32': f32
125 138..142 '1f32': f32
126 145..148 'any': fn any<f32>() -> f32
127 145..150 'any()': f32
128 151..153 '{}': ()
129 158..179 'if let...y() {}': ()
130 165..168 '1.0': f64
131 165..168 '1.0': f64
132 171..174 'any': fn any<f64>() -> f64
133 171..176 'any()': f64
134 177..179 '{}': ()
135 184..206 'if let...y() {}': ()
136 191..195 'true': bool
137 191..195 'true': bool
138 198..201 'any': fn any<bool>() -> bool
139 198..203 'any()': bool
140 204..206 '{}': ()
141 "#]],
142 );
143}
144
145#[test]
146fn infer_range_pattern() {
147 check_infer_with_mismatches(
148 r#"
149 fn test(x: &i32) {
150 if let 1..76 = 2u32 {}
151 if let 1..=76 = 2u32 {}
152 }
153 "#,
154 expect![[r#"
155 8..9 'x': &i32
156 17..75 '{ ...2 {} }': ()
157 23..45 'if let...u32 {}': ()
158 30..35 '1..76': u32
159 38..42 '2u32': u32
160 43..45 '{}': ()
161 50..73 'if let...u32 {}': ()
162 57..63 '1..=76': u32
163 66..70 '2u32': u32
164 71..73 '{}': ()
165 "#]],
166 );
167}
168
169#[test]
170fn infer_pattern_match_ergonomics() {
171 check_infer(
172 r#"
173 struct A<T>(T);
174
175 fn test() {
176 let A(n) = &A(1);
177 let A(n) = &mut A(1);
178 }
179 "#,
180 expect![[r#"
181 27..78 '{ ...(1); }': ()
182 37..41 'A(n)': A<i32>
183 39..40 'n': &i32
184 44..49 '&A(1)': &A<i32>
185 45..46 'A': A<i32>(i32) -> A<i32>
186 45..49 'A(1)': A<i32>
187 47..48 '1': i32
188 59..63 'A(n)': A<i32>
189 61..62 'n': &mut i32
190 66..75 '&mut A(1)': &mut A<i32>
191 71..72 'A': A<i32>(i32) -> A<i32>
192 71..75 'A(1)': A<i32>
193 73..74 '1': i32
194 "#]],
195 );
196}
197
198#[test]
199fn infer_pattern_match_ergonomics_ref() {
200 mark::check!(match_ergonomics_ref);
201 check_infer(
202 r#"
203 fn test() {
204 let v = &(1, &2);
205 let (_, &w) = v;
206 }
207 "#,
208 expect![[r#"
209 10..56 '{ ...= v; }': ()
210 20..21 'v': &(i32, &i32)
211 24..32 '&(1, &2)': &(i32, &i32)
212 25..32 '(1, &2)': (i32, &i32)
213 26..27 '1': i32
214 29..31 '&2': &i32
215 30..31 '2': i32
216 42..49 '(_, &w)': (i32, &i32)
217 43..44 '_': i32
218 46..48 '&w': &i32
219 47..48 'w': i32
220 52..53 'v': &(i32, &i32)
221 "#]],
222 );
223}
224
225#[test]
226fn infer_pattern_match_slice() {
227 check_infer(
228 r#"
229 fn test() {
230 let slice: &[f64] = &[0.0];
231 match slice {
232 &[] => {},
233 &[a] => {
234 a;
235 },
236 &[b, c] => {
237 b;
238 c;
239 }
240 _ => {}
241 }
242 }
243 "#,
244 expect![[r#"
245 10..209 '{ ... } }': ()
246 20..25 'slice': &[f64]
247 36..42 '&[0.0]': &[f64; _]
248 37..42 '[0.0]': [f64; _]
249 38..41 '0.0': f64
250 48..207 'match ... }': ()
251 54..59 'slice': &[f64]
252 70..73 '&[]': &[f64]
253 71..73 '[]': [f64]
254 77..79 '{}': ()
255 89..93 '&[a]': &[f64]
256 90..93 '[a]': [f64]
257 91..92 'a': f64
258 97..123 '{ ... }': ()
259 111..112 'a': f64
260 133..140 '&[b, c]': &[f64]
261 134..140 '[b, c]': [f64]
262 135..136 'b': f64
263 138..139 'c': f64
264 144..185 '{ ... }': ()
265 158..159 'b': f64
266 173..174 'c': f64
267 194..195 '_': &[f64]
268 199..201 '{}': ()
269 "#]],
270 );
271}
272
273#[test]
274fn infer_pattern_match_string_literal() {
275 check_infer_with_mismatches(
276 r#"
277 fn test() {
278 let s: &str = "hello";
279 match s {
280 "hello" => {}
281 _ => {}
282 }
283 }
284 "#,
285 expect![[r#"
286 10..98 '{ ... } }': ()
287 20..21 's': &str
288 30..37 '"hello"': &str
289 43..96 'match ... }': ()
290 49..50 's': &str
291 61..68 '"hello"': &str
292 61..68 '"hello"': &str
293 72..74 '{}': ()
294 83..84 '_': &str
295 88..90 '{}': ()
296 "#]],
297 );
298}
299
300#[test]
301fn infer_pattern_match_or() {
302 check_infer_with_mismatches(
303 r#"
304 fn test() {
305 let s: &str = "hello";
306 match s {
307 "hello" | "world" => {}
308 _ => {}
309 }
310 }
311 "#,
312 expect![[r#"
313 10..108 '{ ... } }': ()
314 20..21 's': &str
315 30..37 '"hello"': &str
316 43..106 'match ... }': ()
317 49..50 's': &str
318 61..68 '"hello"': &str
319 61..68 '"hello"': &str
320 61..78 '"hello...world"': &str
321 71..78 '"world"': &str
322 71..78 '"world"': &str
323 82..84 '{}': ()
324 93..94 '_': &str
325 98..100 '{}': ()
326 "#]],
327 );
328}
329
330#[test]
331fn infer_pattern_match_arr() {
332 check_infer(
333 r#"
334 fn test() {
335 let arr: [f64; 2] = [0.0, 1.0];
336 match arr {
337 [1.0, a] => {
338 a;
339 },
340 [b, c] => {
341 b;
342 c;
343 }
344 }
345 }
346 "#,
347 expect![[r#"
348 10..179 '{ ... } }': ()
349 20..23 'arr': [f64; _]
350 36..46 '[0.0, 1.0]': [f64; _]
351 37..40 '0.0': f64
352 42..45 '1.0': f64
353 52..177 'match ... }': ()
354 58..61 'arr': [f64; _]
355 72..80 '[1.0, a]': [f64; _]
356 73..76 '1.0': f64
357 73..76 '1.0': f64
358 78..79 'a': f64
359 84..110 '{ ... }': ()
360 98..99 'a': f64
361 120..126 '[b, c]': [f64; _]
362 121..122 'b': f64
363 124..125 'c': f64
364 130..171 '{ ... }': ()
365 144..145 'b': f64
366 159..160 'c': f64
367 "#]],
368 );
369}
370
371#[test]
372fn infer_adt_pattern() {
373 check_infer(
374 r#"
375 enum E {
376 A { x: usize },
377 B
378 }
379
380 struct S(u32, E);
381
382 fn test() {
383 let e = E::A { x: 3 };
384
385 let S(y, z) = foo;
386 let E::A { x: new_var } = e;
387
388 match e {
389 E::A { x } => x,
390 E::B if foo => 1,
391 E::B => 10,
392 };
393
394 let ref d @ E::A { .. } = e;
395 d;
396 }
397 "#,
398 expect![[r#"
399 67..288 '{ ... d; }': ()
400 77..78 'e': E
401 81..94 'E::A { x: 3 }': E
402 91..92 '3': usize
403 105..112 'S(y, z)': S
404 107..108 'y': u32
405 110..111 'z': E
406 115..118 'foo': S
407 128..147 'E::A {..._var }': E
408 138..145 'new_var': usize
409 150..151 'e': E
410 158..244 'match ... }': usize
411 164..165 'e': E
412 176..186 'E::A { x }': E
413 183..184 'x': usize
414 190..191 'x': usize
415 201..205 'E::B': E
416 209..212 'foo': bool
417 216..217 '1': usize
418 227..231 'E::B': E
419 235..237 '10': usize
420 255..274 'ref d ...{ .. }': &E
421 263..274 'E::A { .. }': E
422 277..278 'e': E
423 284..285 'd': &E
424 "#]],
425 );
426}
427
428#[test]
429fn enum_variant_through_self_in_pattern() {
430 check_infer(
431 r#"
432 enum E {
433 A { x: usize },
434 B(usize),
435 C
436 }
437
438 impl E {
439 fn test() {
440 match (loop {}) {
441 Self::A { x } => { x; },
442 Self::B(x) => { x; },
443 Self::C => {},
444 };
445 }
446 }
447 "#,
448 expect![[r#"
449 75..217 '{ ... }': ()
450 85..210 'match ... }': ()
451 92..99 'loop {}': !
452 97..99 '{}': ()
453 115..128 'Self::A { x }': E
454 125..126 'x': usize
455 132..138 '{ x; }': ()
456 134..135 'x': usize
457 152..162 'Self::B(x)': E
458 160..161 'x': usize
459 166..172 '{ x; }': ()
460 168..169 'x': usize
461 186..193 'Self::C': E
462 197..199 '{}': ()
463 "#]],
464 );
465}
466
467#[test]
468fn infer_generics_in_patterns() {
469 check_infer(
470 r#"
471 struct A<T> {
472 x: T,
473 }
474
475 enum Option<T> {
476 Some(T),
477 None,
478 }
479
480 fn test(a1: A<u32>, o: Option<u64>) {
481 let A { x: x2 } = a1;
482 let A::<i64> { x: x3 } = A { x: 1 };
483 match o {
484 Option::Some(t) => t,
485 _ => 1,
486 };
487 }
488 "#,
489 expect![[r#"
490 78..80 'a1': A<u32>
491 90..91 'o': Option<u64>
492 106..243 '{ ... }; }': ()
493 116..127 'A { x: x2 }': A<u32>
494 123..125 'x2': u32
495 130..132 'a1': A<u32>
496 142..160 'A::<i6...: x3 }': A<i64>
497 156..158 'x3': i64
498 163..173 'A { x: 1 }': A<i64>
499 170..171 '1': i64
500 179..240 'match ... }': u64
501 185..186 'o': Option<u64>
502 197..212 'Option::Some(t)': Option<u64>
503 210..211 't': u64
504 216..217 't': u64
505 227..228 '_': Option<u64>
506 232..233 '1': u64
507 "#]],
508 );
509}
510
511#[test]
512fn infer_const_pattern() {
513 check_infer_with_mismatches(
514 r#"
515 enum Option<T> { None }
516 use Option::None;
517 struct Foo;
518 const Bar: usize = 1;
519
520 fn test() {
521 let a: Option<u32> = None;
522 let b: Option<i64> = match a {
523 None => None,
524 };
525 let _: () = match () { Foo => Foo }; // Expected mismatch
526 let _: () = match () { Bar => Bar }; // Expected mismatch
527 }
528 "#,
529 expect![[r#"
530 73..74 '1': usize
531 87..309 '{ ...atch }': ()
532 97..98 'a': Option<u32>
533 114..118 'None': Option<u32>
534 128..129 'b': Option<i64>
535 145..182 'match ... }': Option<i64>
536 151..152 'a': Option<u32>
537 163..167 'None': Option<u32>
538 171..175 'None': Option<i64>
539 192..193 '_': ()
540 200..223 'match ... Foo }': Foo
541 206..208 '()': ()
542 211..214 'Foo': Foo
543 218..221 'Foo': Foo
544 254..255 '_': ()
545 262..285 'match ... Bar }': usize
546 268..270 '()': ()
547 273..276 'Bar': usize
548 280..283 'Bar': usize
549 200..223: expected (), got Foo
550 262..285: expected (), got usize
551 "#]],
552 );
553}
554
555#[test]
556fn infer_guard() {
557 check_infer(
558 r#"
559struct S;
560impl S { fn foo(&self) -> bool { false } }
561
562fn main() {
563 match S {
564 s if s.foo() => (),
565 }
566}
567 "#,
568 expect![[r#"
569 27..31 'self': &S
570 41..50 '{ false }': bool
571 43..48 'false': bool
572 64..115 '{ ... } }': ()
573 70..113 'match ... }': ()
574 76..77 'S': S
575 88..89 's': S
576 93..94 's': S
577 93..100 's.foo()': bool
578 104..106 '()': ()
579 "#]],
580 )
581}
582
583#[test]
584fn match_ergonomics_in_closure_params() {
585 check_infer(
586 r#"
587 #[lang = "fn_once"]
588 trait FnOnce<Args> {
589 type Output;
590 }
591
592 fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} }
593
594 fn test() {
595 foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics
596 foo(&(1, "a"), |(x, y)| x);
597 }
598 "#,
599 expect![[r#"
600 93..94 't': T
601 99..100 'f': F
602 110..121 '{ loop {} }': U
603 112..119 'loop {}': !
604 117..119 '{}': ()
605 133..232 '{ ... x); }': ()
606 139..142 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32
607 139..166 'foo(&(...y)| x)': i32
608 143..152 '&(1, "a")': &(i32, &str)
609 144..152 '(1, "a")': (i32, &str)
610 145..146 '1': i32
611 148..151 '"a"': &str
612 154..165 '|&(x, y)| x': |&(i32, &str)| -> i32
613 155..162 '&(x, y)': &(i32, &str)
614 156..162 '(x, y)': (i32, &str)
615 157..158 'x': i32
616 160..161 'y': &str
617 164..165 'x': i32
618 203..206 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32
619 203..229 'foo(&(...y)| x)': &i32
620 207..216 '&(1, "a")': &(i32, &str)
621 208..216 '(1, "a")': (i32, &str)
622 209..210 '1': i32
623 212..215 '"a"': &str
624 218..228 '|(x, y)| x': |&(i32, &str)| -> &i32
625 219..225 '(x, y)': (i32, &str)
626 220..221 'x': &i32
627 223..224 'y': &&str
628 227..228 'x': &i32
629 "#]],
630 );
631}
632
633#[test]
634fn slice_tail_pattern() {
635 check_infer(
636 r#"
637 fn foo(params: &[i32]) {
638 match params {
639 [head, tail @ ..] => {
640 }
641 }
642 }
643 "#,
644 expect![[r#"
645 7..13 'params': &[i32]
646 23..92 '{ ... } }': ()
647 29..90 'match ... }': ()
648 35..41 'params': &[i32]
649 52..69 '[head,... @ ..]': [i32]
650 53..57 'head': &i32
651 59..68 'tail @ ..': &[i32]
652 66..68 '..': [i32]
653 73..84 '{ }': ()
654 "#]],
655 );
656}