]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/patterns.rs
Merge #7994
[rust.git] / crates / hir_ty / src / tests / patterns.rs
1 use expect_test::expect;
2
3 use super::{check_infer, check_infer_with_mismatches};
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             let lambda = |a: u64, b, c: i32| { a + b; c };
24
25             let ref ref_to_x = x;
26             let mut mut_x = x;
27             let ref mut mut_ref_to_x = x;
28             let k = mut_ref_to_x;
29         }
30         "#,
31         expect![[r#"
32             8..9 'x': &i32
33             17..368 '{     ...o_x; }': ()
34             27..28 'y': &i32
35             31..32 'x': &i32
36             42..44 '&z': &i32
37             43..44 'z': i32
38             47..48 'x': &i32
39             58..59 'a': i32
40             62..63 'z': i32
41             73..79 '(c, d)': (i32, &str)
42             74..75 'c': i32
43             77..78 'd': &str
44             82..94 '(1, "hello")': (i32, &str)
45             83..84 '1': i32
46             86..93 '"hello"': &str
47             101..151 'for (e...     }': ()
48             105..111 '(e, f)': ({unknown}, {unknown})
49             106..107 'e': {unknown}
50             109..110 'f': {unknown}
51             115..124 'some_iter': {unknown}
52             125..151 '{     ...     }': ()
53             139..140 'g': {unknown}
54             143..144 'e': {unknown}
55             157..204 'if let...     }': ()
56             164..169 '[val]': [{unknown}]
57             165..168 'val': {unknown}
58             172..175 'opt': [{unknown}]
59             176..204 '{     ...     }': ()
60             190..191 'h': {unknown}
61             194..197 'val': {unknown}
62             214..220 'lambda': |u64, u64, i32| -> i32
63             223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32
64             224..225 'a': u64
65             232..233 'b': u64
66             235..236 'c': i32
67             243..255 '{ a + b; c }': i32
68             245..246 'a': u64
69             245..250 'a + b': u64
70             249..250 'b': u64
71             252..253 'c': i32
72             266..278 'ref ref_to_x': &&i32
73             281..282 'x': &i32
74             292..301 'mut mut_x': &i32
75             304..305 'x': &i32
76             315..335 'ref mu...f_to_x': &mut &i32
77             338..339 'x': &i32
78             349..350 'k': &mut &i32
79             353..365 'mut_ref_to_x': &mut &i32
80         "#]],
81     );
82 }
83
84 #[test]
85 fn infer_literal_pattern() {
86     check_infer_with_mismatches(
87         r#"
88         fn any<T>() -> T { loop {} }
89         fn test(x: &i32) {
90             if let "foo" = any() {}
91             if let 1 = any() {}
92             if let 1u32 = any() {}
93             if let 1f32 = any() {}
94             if let 1.0 = any() {}
95             if let true = any() {}
96         }
97         "#,
98         expect![[r#"
99             17..28 '{ loop {} }': T
100             19..26 'loop {}': !
101             24..26 '{}': ()
102             37..38 'x': &i32
103             46..208 '{     ...) {} }': ()
104             52..75 'if let...y() {}': ()
105             59..64 '"foo"': &str
106             59..64 '"foo"': &str
107             67..70 'any': fn any<&str>() -> &str
108             67..72 'any()': &str
109             73..75 '{}': ()
110             80..99 'if let...y() {}': ()
111             87..88 '1': i32
112             87..88 '1': i32
113             91..94 'any': fn any<i32>() -> i32
114             91..96 'any()': i32
115             97..99 '{}': ()
116             104..126 'if let...y() {}': ()
117             111..115 '1u32': u32
118             111..115 '1u32': u32
119             118..121 'any': fn any<u32>() -> u32
120             118..123 'any()': u32
121             124..126 '{}': ()
122             131..153 'if let...y() {}': ()
123             138..142 '1f32': f32
124             138..142 '1f32': f32
125             145..148 'any': fn any<f32>() -> f32
126             145..150 'any()': f32
127             151..153 '{}': ()
128             158..179 'if let...y() {}': ()
129             165..168 '1.0': f64
130             165..168 '1.0': f64
131             171..174 'any': fn any<f64>() -> f64
132             171..176 'any()': f64
133             177..179 '{}': ()
134             184..206 'if let...y() {}': ()
135             191..195 'true': bool
136             191..195 'true': bool
137             198..201 'any': fn any<bool>() -> bool
138             198..203 'any()': bool
139             204..206 '{}': ()
140         "#]],
141     );
142 }
143
144 #[test]
145 fn infer_range_pattern() {
146     check_infer_with_mismatches(
147         r#"
148         fn test(x: &i32) {
149             if let 1..76 = 2u32 {}
150             if let 1..=76 = 2u32 {}
151         }
152         "#,
153         expect![[r#"
154             8..9 'x': &i32
155             17..75 '{     ...2 {} }': ()
156             23..45 'if let...u32 {}': ()
157             30..35 '1..76': u32
158             38..42 '2u32': u32
159             43..45 '{}': ()
160             50..73 'if let...u32 {}': ()
161             57..63 '1..=76': u32
162             66..70 '2u32': u32
163             71..73 '{}': ()
164         "#]],
165     );
166 }
167
168 #[test]
169 fn infer_pattern_match_ergonomics() {
170     check_infer(
171         r#"
172         struct A<T>(T);
173
174         fn test() {
175             let A(n) = &A(1);
176             let A(n) = &mut A(1);
177         }
178         "#,
179         expect![[r#"
180             27..78 '{     ...(1); }': ()
181             37..41 'A(n)': A<i32>
182             39..40 'n': &i32
183             44..49 '&A(1)': &A<i32>
184             45..46 'A': A<i32>(i32) -> A<i32>
185             45..49 'A(1)': A<i32>
186             47..48 '1': i32
187             59..63 'A(n)': A<i32>
188             61..62 'n': &mut i32
189             66..75 '&mut A(1)': &mut A<i32>
190             71..72 'A': A<i32>(i32) -> A<i32>
191             71..75 'A(1)': A<i32>
192             73..74 '1': i32
193         "#]],
194     );
195 }
196
197 #[test]
198 fn infer_pattern_match_ergonomics_ref() {
199     cov_mark::check!(match_ergonomics_ref);
200     check_infer(
201         r#"
202         fn test() {
203             let v = &(1, &2);
204             let (_, &w) = v;
205         }
206         "#,
207         expect![[r#"
208             10..56 '{     ...= v; }': ()
209             20..21 'v': &(i32, &i32)
210             24..32 '&(1, &2)': &(i32, &i32)
211             25..32 '(1, &2)': (i32, &i32)
212             26..27 '1': i32
213             29..31 '&2': &i32
214             30..31 '2': i32
215             42..49 '(_, &w)': (i32, &i32)
216             43..44 '_': i32
217             46..48 '&w': &i32
218             47..48 'w': i32
219             52..53 'v': &(i32, &i32)
220         "#]],
221     );
222 }
223
224 #[test]
225 fn infer_pattern_match_slice() {
226     check_infer(
227         r#"
228         fn test() {
229             let slice: &[f64] = &[0.0];
230             match slice {
231                 &[] => {},
232                 &[a] => {
233                     a;
234                 },
235                 &[b, c] => {
236                     b;
237                     c;
238                 }
239                 _ => {}
240             }
241         }
242         "#,
243         expect![[r#"
244             10..209 '{     ...   } }': ()
245             20..25 'slice': &[f64]
246             36..42 '&[0.0]': &[f64; _]
247             37..42 '[0.0]': [f64; _]
248             38..41 '0.0': f64
249             48..207 'match ...     }': ()
250             54..59 'slice': &[f64]
251             70..73 '&[]': &[f64]
252             71..73 '[]': [f64]
253             77..79 '{}': ()
254             89..93 '&[a]': &[f64]
255             90..93 '[a]': [f64]
256             91..92 'a': f64
257             97..123 '{     ...     }': ()
258             111..112 'a': f64
259             133..140 '&[b, c]': &[f64]
260             134..140 '[b, c]': [f64]
261             135..136 'b': f64
262             138..139 'c': f64
263             144..185 '{     ...     }': ()
264             158..159 'b': f64
265             173..174 'c': f64
266             194..195 '_': &[f64]
267             199..201 '{}': ()
268         "#]],
269     );
270 }
271
272 #[test]
273 fn infer_pattern_match_string_literal() {
274     check_infer_with_mismatches(
275         r#"
276         fn test() {
277             let s: &str = "hello";
278             match s {
279                 "hello" => {}
280                 _ => {}
281             }
282         }
283         "#,
284         expect![[r#"
285             10..98 '{     ...   } }': ()
286             20..21 's': &str
287             30..37 '"hello"': &str
288             43..96 'match ...     }': ()
289             49..50 's': &str
290             61..68 '"hello"': &str
291             61..68 '"hello"': &str
292             72..74 '{}': ()
293             83..84 '_': &str
294             88..90 '{}': ()
295         "#]],
296     );
297 }
298
299 #[test]
300 fn infer_pattern_match_or() {
301     check_infer_with_mismatches(
302         r#"
303         fn test() {
304             let s: &str = "hello";
305             match s {
306                 "hello" | "world" => {}
307                 _ => {}
308             }
309         }
310         "#,
311         expect![[r#"
312             10..108 '{     ...   } }': ()
313             20..21 's': &str
314             30..37 '"hello"': &str
315             43..106 'match ...     }': ()
316             49..50 's': &str
317             61..68 '"hello"': &str
318             61..68 '"hello"': &str
319             61..78 '"hello...world"': &str
320             71..78 '"world"': &str
321             71..78 '"world"': &str
322             82..84 '{}': ()
323             93..94 '_': &str
324             98..100 '{}': ()
325         "#]],
326     );
327 }
328
329 #[test]
330 fn infer_pattern_match_arr() {
331     check_infer(
332         r#"
333         fn test() {
334             let arr: [f64; 2] = [0.0, 1.0];
335             match arr {
336                 [1.0, a] => {
337                     a;
338                 },
339                 [b, c] => {
340                     b;
341                     c;
342                 }
343             }
344         }
345         "#,
346         expect![[r#"
347             10..179 '{     ...   } }': ()
348             20..23 'arr': [f64; _]
349             36..46 '[0.0, 1.0]': [f64; _]
350             37..40 '0.0': f64
351             42..45 '1.0': f64
352             52..177 'match ...     }': ()
353             58..61 'arr': [f64; _]
354             72..80 '[1.0, a]': [f64; _]
355             73..76 '1.0': f64
356             73..76 '1.0': f64
357             78..79 'a': f64
358             84..110 '{     ...     }': ()
359             98..99 'a': f64
360             120..126 '[b, c]': [f64; _]
361             121..122 'b': f64
362             124..125 'c': f64
363             130..171 '{     ...     }': ()
364             144..145 'b': f64
365             159..160 'c': f64
366         "#]],
367     );
368 }
369
370 #[test]
371 fn infer_adt_pattern() {
372     check_infer(
373         r#"
374         enum E {
375             A { x: usize },
376             B
377         }
378
379         struct S(u32, E);
380
381         fn test() {
382             let e = E::A { x: 3 };
383
384             let S(y, z) = foo;
385             let E::A { x: new_var } = e;
386
387             match e {
388                 E::A { x } => x,
389                 E::B if foo => 1,
390                 E::B => 10,
391             };
392
393             let ref d @ E::A { .. } = e;
394             d;
395         }
396         "#,
397         expect![[r#"
398             67..288 '{     ...  d; }': ()
399             77..78 'e': E
400             81..94 'E::A { x: 3 }': E
401             91..92 '3': usize
402             105..112 'S(y, z)': S
403             107..108 'y': u32
404             110..111 'z': E
405             115..118 'foo': S
406             128..147 'E::A {..._var }': E
407             138..145 'new_var': usize
408             150..151 'e': E
409             158..244 'match ...     }': usize
410             164..165 'e': E
411             176..186 'E::A { x }': E
412             183..184 'x': usize
413             190..191 'x': usize
414             201..205 'E::B': E
415             209..212 'foo': bool
416             216..217 '1': usize
417             227..231 'E::B': E
418             235..237 '10': usize
419             255..274 'ref d ...{ .. }': &E
420             263..274 'E::A { .. }': E
421             277..278 'e': E
422             284..285 'd': &E
423         "#]],
424     );
425 }
426
427 #[test]
428 fn enum_variant_through_self_in_pattern() {
429     check_infer(
430         r#"
431         enum E {
432             A { x: usize },
433             B(usize),
434             C
435         }
436
437         impl E {
438             fn test() {
439                 match (loop {}) {
440                     Self::A { x } => { x; },
441                     Self::B(x) => { x; },
442                     Self::C => {},
443                 };
444             }
445         }
446         "#,
447         expect![[r#"
448             75..217 '{     ...     }': ()
449             85..210 'match ...     }': ()
450             92..99 'loop {}': !
451             97..99 '{}': ()
452             115..128 'Self::A { x }': E
453             125..126 'x': usize
454             132..138 '{ x; }': ()
455             134..135 'x': usize
456             152..162 'Self::B(x)': E
457             160..161 'x': usize
458             166..172 '{ x; }': ()
459             168..169 'x': usize
460             186..193 'Self::C': E
461             197..199 '{}': ()
462         "#]],
463     );
464 }
465
466 #[test]
467 fn infer_generics_in_patterns() {
468     check_infer(
469         r#"
470         struct A<T> {
471             x: T,
472         }
473
474         enum Option<T> {
475             Some(T),
476             None,
477         }
478
479         fn test(a1: A<u32>, o: Option<u64>) {
480             let A { x: x2 } = a1;
481             let A::<i64> { x: x3 } = A { x: 1 };
482             match o {
483                 Option::Some(t) => t,
484                 _ => 1,
485             };
486         }
487         "#,
488         expect![[r#"
489             78..80 'a1': A<u32>
490             90..91 'o': Option<u64>
491             106..243 '{     ...  }; }': ()
492             116..127 'A { x: x2 }': A<u32>
493             123..125 'x2': u32
494             130..132 'a1': A<u32>
495             142..160 'A::<i6...: x3 }': A<i64>
496             156..158 'x3': i64
497             163..173 'A { x: 1 }': A<i64>
498             170..171 '1': i64
499             179..240 'match ...     }': u64
500             185..186 'o': Option<u64>
501             197..212 'Option::Some(t)': Option<u64>
502             210..211 't': u64
503             216..217 't': u64
504             227..228 '_': Option<u64>
505             232..233 '1': u64
506         "#]],
507     );
508 }
509
510 #[test]
511 fn infer_const_pattern() {
512     check_infer_with_mismatches(
513         r#"
514         enum Option<T> { None }
515         use Option::None;
516         struct Foo;
517         const Bar: usize = 1;
518
519         fn test() {
520             let a: Option<u32> = None;
521             let b: Option<i64> = match a {
522                 None => None,
523             };
524             let _: () = match () { Foo => Foo }; // Expected mismatch
525             let _: () = match () { Bar => Bar }; // Expected mismatch
526         }
527         "#,
528         expect![[r#"
529             73..74 '1': usize
530             87..309 '{     ...atch }': ()
531             97..98 'a': Option<u32>
532             114..118 'None': Option<u32>
533             128..129 'b': Option<i64>
534             145..182 'match ...     }': Option<i64>
535             151..152 'a': Option<u32>
536             163..167 'None': Option<u32>
537             171..175 'None': Option<i64>
538             192..193 '_': ()
539             200..223 'match ... Foo }': Foo
540             206..208 '()': ()
541             211..214 'Foo': Foo
542             218..221 'Foo': Foo
543             254..255 '_': ()
544             262..285 'match ... Bar }': usize
545             268..270 '()': ()
546             273..276 'Bar': usize
547             280..283 'Bar': usize
548             200..223: expected (), got Foo
549             262..285: expected (), got usize
550         "#]],
551     );
552 }
553
554 #[test]
555 fn infer_guard() {
556     check_infer(
557         r#"
558 struct S;
559 impl S { fn foo(&self) -> bool { false } }
560
561 fn main() {
562     match S {
563         s if s.foo() => (),
564     }
565 }
566         "#,
567         expect![[r#"
568             27..31 'self': &S
569             41..50 '{ false }': bool
570             43..48 'false': bool
571             64..115 '{     ...   } }': ()
572             70..113 'match ...     }': ()
573             76..77 'S': S
574             88..89 's': S
575             93..94 's': S
576             93..100 's.foo()': bool
577             104..106 '()': ()
578     "#]],
579     )
580 }
581
582 #[test]
583 fn match_ergonomics_in_closure_params() {
584     check_infer(
585         r#"
586         #[lang = "fn_once"]
587         trait FnOnce<Args> {
588             type Output;
589         }
590
591         fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} }
592
593         fn test() {
594             foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics
595             foo(&(1, "a"), |(x, y)| x);
596         }
597         "#,
598         expect![[r#"
599             93..94 't': T
600             99..100 'f': F
601             110..121 '{ loop {} }': U
602             112..119 'loop {}': !
603             117..119 '{}': ()
604             133..232 '{     ... x); }': ()
605             139..142 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32
606             139..166 'foo(&(...y)| x)': i32
607             143..152 '&(1, "a")': &(i32, &str)
608             144..152 '(1, "a")': (i32, &str)
609             145..146 '1': i32
610             148..151 '"a"': &str
611             154..165 '|&(x, y)| x': |&(i32, &str)| -> i32
612             155..162 '&(x, y)': &(i32, &str)
613             156..162 '(x, y)': (i32, &str)
614             157..158 'x': i32
615             160..161 'y': &str
616             164..165 'x': i32
617             203..206 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32
618             203..229 'foo(&(...y)| x)': &i32
619             207..216 '&(1, "a")': &(i32, &str)
620             208..216 '(1, "a")': (i32, &str)
621             209..210 '1': i32
622             212..215 '"a"': &str
623             218..228 '|(x, y)| x': |&(i32, &str)| -> &i32
624             219..225 '(x, y)': (i32, &str)
625             220..221 'x': &i32
626             223..224 'y': &&str
627             227..228 'x': &i32
628         "#]],
629     );
630 }
631
632 #[test]
633 fn slice_tail_pattern() {
634     check_infer(
635         r#"
636         fn foo(params: &[i32]) {
637             match params {
638                 [head, tail @ ..] => {
639                 }
640             }
641         }
642         "#,
643         expect![[r#"
644             7..13 'params': &[i32]
645             23..92 '{     ...   } }': ()
646             29..90 'match ...     }': ()
647             35..41 'params': &[i32]
648             52..69 '[head,... @ ..]': [i32]
649             53..57 'head': &i32
650             59..68 'tail @ ..': &[i32]
651             66..68 '..': [i32]
652             73..84 '{         }': ()
653         "#]],
654     );
655 }
656
657 #[test]
658 fn box_pattern() {
659     check_infer(
660         r#"
661         #[lang = "owned_box"]
662         pub struct Box<T>(T);
663
664         fn foo(params: Box<i32>) {
665             match params {
666                 box integer => {}
667             }
668         }
669         "#,
670         expect![[r#"
671             52..58 'params': Box<i32>
672             70..124 '{     ...   } }': ()
673             76..122 'match ...     }': ()
674             82..88 'params': Box<i32>
675             99..110 'box integer': Box<i32>
676             103..110 'integer': i32
677             114..116 '{}': ()
678         "#]],
679     );
680 }
681
682 #[test]
683 fn tuple_ellipsis_pattern() {
684     check_infer(
685         r#"
686 fn foo(tuple: (u8, i16, f32)) {
687     match tuple {
688         (.., b, c) => {},
689         (a, .., c) => {},
690         (a, b, ..) => {},
691         (a, b) => {/*too short*/}
692         (a, b, c, d) => {/*too long*/}
693         _ => {}
694     }
695 }"#,
696         expect![[r#"
697             7..12 'tuple': (u8, i16, f32)
698             30..224 '{     ...   } }': ()
699             36..222 'match ...     }': ()
700             42..47 'tuple': (u8, i16, f32)
701             58..68 '(.., b, c)': (u8, i16, f32)
702             63..64 'b': i16
703             66..67 'c': f32
704             72..74 '{}': ()
705             84..94 '(a, .., c)': (u8, i16, f32)
706             85..86 'a': u8
707             92..93 'c': f32
708             98..100 '{}': ()
709             110..120 '(a, b, ..)': (u8, i16, f32)
710             111..112 'a': u8
711             114..115 'b': i16
712             124..126 '{}': ()
713             136..142 '(a, b)': (u8, i16, f32)
714             137..138 'a': u8
715             140..141 'b': i16
716             146..161 '{/*too short*/}': ()
717             170..182 '(a, b, c, d)': (u8, i16, f32, {unknown})
718             171..172 'a': u8
719             174..175 'b': i16
720             177..178 'c': f32
721             180..181 'd': {unknown}
722             186..200 '{/*too long*/}': ()
723             209..210 '_': (u8, i16, f32)
724             214..216 '{}': ()
725         "#]],
726     );
727 }
728
729 #[test]
730 fn tuple_struct_ellipsis_pattern() {
731     check_infer(
732         r#"
733 struct Tuple(u8, i16, f32);
734 fn foo(tuple: Tuple) {
735     match tuple {
736         Tuple(.., b, c) => {},
737         Tuple(a, .., c) => {},
738         Tuple(a, b, ..) => {},
739         Tuple(a, b) => {/*too short*/}
740         Tuple(a, b, c, d) => {/*too long*/}
741         _ => {}
742     }
743 }"#,
744         expect![[r#"
745             35..40 'tuple': Tuple
746             49..268 '{     ...   } }': ()
747             55..266 'match ...     }': ()
748             61..66 'tuple': Tuple
749             77..92 'Tuple(.., b, c)': Tuple
750             87..88 'b': i16
751             90..91 'c': f32
752             96..98 '{}': ()
753             108..123 'Tuple(a, .., c)': Tuple
754             114..115 'a': u8
755             121..122 'c': f32
756             127..129 '{}': ()
757             139..154 'Tuple(a, b, ..)': Tuple
758             145..146 'a': u8
759             148..149 'b': i16
760             158..160 '{}': ()
761             170..181 'Tuple(a, b)': Tuple
762             176..177 'a': u8
763             179..180 'b': i16
764             185..200 '{/*too short*/}': ()
765             209..226 'Tuple(... c, d)': Tuple
766             215..216 'a': u8
767             218..219 'b': i16
768             221..222 'c': f32
769             224..225 'd': {unknown}
770             230..244 '{/*too long*/}': ()
771             253..254 '_': Tuple
772             258..260 '{}': ()
773         "#]],
774     );
775 }
776
777 #[test]
778 fn const_block_pattern() {
779     check_infer(
780         r#"
781 struct Foo(usize);
782 fn foo(foo: Foo) {
783     match foo {
784         const { Foo(15 + 32) } => {},
785         _ => {}
786     }
787 }"#,
788         expect![[r#"
789             26..29 'foo': Foo
790             36..115 '{     ...   } }': ()
791             42..113 'match ...     }': ()
792             48..51 'foo': Foo
793             62..84 'const ... 32) }': Foo
794             68..84 '{ Foo(... 32) }': Foo
795             70..73 'Foo': Foo(usize) -> Foo
796             70..82 'Foo(15 + 32)': Foo
797             74..76 '15': usize
798             74..81 '15 + 32': usize
799             79..81 '32': usize
800             88..90 '{}': ()
801             100..101 '_': Foo
802             105..107 '{}': ()
803         "#]],
804     );
805 }