Skip to content

Commit b71fc18

Browse files
Merge #3387
3387: Type inference for slice patterns r=flodiebold a=JoshMcguigan Fixes #3043 Notes to reviewer: 1. This only works if `expected` is `Ty::Apply`. I'm not sure of the implications of this. 1. This only works if the slice pattern only has a prefix. I think this means it doesn't work for subslice patterns, which are currently only available behind a feature flag. Co-authored-by: Josh Mcguigan <[email protected]>
2 parents ea67e23 + f5efa17 commit b71fc18

File tree

2 files changed

+108
-2
lines changed

2 files changed

+108
-2
lines changed

crates/ra_hir_ty/src/infer/pat.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
185185
self.write_pat_ty(pat, bound_ty);
186186
return inner_ty;
187187
}
188+
Pat::Slice { prefix, slice: _slice, suffix } => {
189+
let (container_ty, elem_ty) = match &expected {
190+
ty_app!(TypeCtor::Array, st) => {
191+
(TypeCtor::Array, st.as_single().clone())
192+
},
193+
ty_app!(TypeCtor::Slice, st) => {
194+
(TypeCtor::Slice, st.as_single().clone())
195+
},
196+
_ => (TypeCtor::Slice, Ty::Unknown),
197+
};
198+
199+
for pat_id in prefix.iter().chain(suffix) {
200+
self.infer_pat(*pat_id, &elem_ty, default_bm);
201+
}
202+
203+
Ty::apply_one(container_ty, elem_ty)
204+
}
188205
_ => Ty::Unknown,
189206
};
190207
// use a new type variable if we got Ty::Unknown here

crates/ra_hir_ty/src/tests/patterns.rs

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ fn test(x: &i32) {
5353
[140; 141) 'g': {unknown}
5454
[144; 145) 'e': {unknown}
5555
[158; 205) 'if let... }': ()
56-
[165; 170) '[val]': {unknown}
57-
[173; 176) 'opt': {unknown}
56+
[165; 170) '[val]': [{unknown}]
57+
[166; 169) 'val': {unknown}
58+
[173; 176) 'opt': [{unknown}]
5859
[177; 205) '{ ... }': ()
5960
[191; 192) 'h': {unknown}
6061
[195; 198) 'val': {unknown}
@@ -136,6 +137,94 @@ fn test() {
136137
);
137138
}
138139

140+
#[test]
141+
fn infer_pattern_match_slice() {
142+
assert_snapshot!(
143+
infer(r#"
144+
fn test() {
145+
let slice: &[f64] = &[0.0];
146+
match slice {
147+
&[] => {},
148+
&[a] => {
149+
a;
150+
},
151+
&[b, c] => {
152+
b;
153+
c;
154+
}
155+
_ => {}
156+
}
157+
}
158+
"#),
159+
@r###"
160+
[11; 210) '{ ... } }': ()
161+
[21; 26) 'slice': &[f64]
162+
[37; 43) '&[0.0]': &[f64; _]
163+
[38; 43) '[0.0]': [f64; _]
164+
[39; 42) '0.0': f64
165+
[49; 208) 'match ... }': ()
166+
[55; 60) 'slice': &[f64]
167+
[71; 74) '&[]': &[f64]
168+
[72; 74) '[]': [f64]
169+
[78; 80) '{}': ()
170+
[90; 94) '&[a]': &[f64]
171+
[91; 94) '[a]': [f64]
172+
[92; 93) 'a': f64
173+
[98; 124) '{ ... }': ()
174+
[112; 113) 'a': f64
175+
[134; 141) '&[b, c]': &[f64]
176+
[135; 141) '[b, c]': [f64]
177+
[136; 137) 'b': f64
178+
[139; 140) 'c': f64
179+
[145; 186) '{ ... }': ()
180+
[159; 160) 'b': f64
181+
[174; 175) 'c': f64
182+
[195; 196) '_': &[f64]
183+
[200; 202) '{}': ()
184+
"###
185+
);
186+
}
187+
188+
#[test]
189+
fn infer_pattern_match_arr() {
190+
assert_snapshot!(
191+
infer(r#"
192+
fn test() {
193+
let arr: [f64; 2] = [0.0, 1.0];
194+
match arr {
195+
[1.0, a] => {
196+
a;
197+
},
198+
[b, c] => {
199+
b;
200+
c;
201+
}
202+
}
203+
}
204+
"#),
205+
@r###"
206+
[11; 180) '{ ... } }': ()
207+
[21; 24) 'arr': [f64; _]
208+
[37; 47) '[0.0, 1.0]': [f64; _]
209+
[38; 41) '0.0': f64
210+
[43; 46) '1.0': f64
211+
[53; 178) 'match ... }': ()
212+
[59; 62) 'arr': [f64; _]
213+
[73; 81) '[1.0, a]': [f64; _]
214+
[74; 77) '1.0': f64
215+
[79; 80) 'a': f64
216+
[85; 111) '{ ... }': ()
217+
[99; 100) 'a': f64
218+
[121; 127) '[b, c]': [f64; _]
219+
[122; 123) 'b': f64
220+
[125; 126) 'c': f64
221+
[131; 172) '{ ... }': ()
222+
[145; 146) 'b': f64
223+
[160; 161) 'c': f64
224+
"###
225+
);
226+
}
227+
139228
#[test]
140229
fn infer_adt_pattern() {
141230
assert_snapshot!(

0 commit comments

Comments
 (0)