]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/patterns.rs
Merge #5987
[rust.git] / crates / hir_ty / src / tests / patterns.rs
1 use expect_test::expect;
2 use test_utils::mark;
3
4 use super::{check_infer, check_infer_with_mismatches};
5
6 #[test]
7 fn 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]
86 fn 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]
146 fn 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]
170 fn 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]
199 fn 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]
226 fn 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]
274 fn 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]
301 fn 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]
331 fn 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]
372 fn 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]
429 fn 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]
468 fn 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]
512 fn 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]
556 fn infer_guard() {
557     check_infer(
558         r#"
559 struct S;
560 impl S { fn foo(&self) -> bool { false } }
561
562 fn 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]
584 fn 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]
634 fn 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 }
657
658 #[test]
659 fn box_pattern() {
660     check_infer(
661         r#"
662         #[lang = "owned_box"]
663         pub struct Box<T>(T);
664
665         fn foo(params: Box<i32>) {
666             match params {
667                 box integer => {}
668             }
669         }
670         "#,
671         expect![[r#"
672             52..58 'params': Box<i32>
673             70..124 '{     ...   } }': ()
674             76..122 'match ...     }': ()
675             82..88 'params': Box<i32>
676             99..110 'box integer': Box<i32>
677             103..110 'integer': i32
678             114..116 '{}': ()
679         "#]],
680     );
681 }