diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-01 22:36:47 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-01 22:36:47 +0000 |
commit | b71fc18abe6e9572a3ca3ae18597fe05121095af (patch) | |
tree | 8d6624c9efe2626f52bec77a0513ee6335e76498 /crates | |
parent | ea67e2346e64a1a14206e6d0f163c6c2e19d0afb (diff) | |
parent | f5efa17515a543c1405ecad2caf93ed25052500e (diff) |
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]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/patterns.rs | 93 |
2 files changed, 108 insertions, 2 deletions
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index bf8ea192b..623e52599 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -185,6 +185,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
185 | self.write_pat_ty(pat, bound_ty); | 185 | self.write_pat_ty(pat, bound_ty); |
186 | return inner_ty; | 186 | return inner_ty; |
187 | } | 187 | } |
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 | } | ||
188 | _ => Ty::Unknown, | 205 | _ => Ty::Unknown, |
189 | }; | 206 | }; |
190 | // use a new type variable if we got Ty::Unknown here | 207 | // use a new type variable if we got Ty::Unknown here |
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 81d00c2af..76aa32024 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -53,8 +53,9 @@ fn test(x: &i32) { | |||
53 | [140; 141) 'g': {unknown} | 53 | [140; 141) 'g': {unknown} |
54 | [144; 145) 'e': {unknown} | 54 | [144; 145) 'e': {unknown} |
55 | [158; 205) 'if let... }': () | 55 | [158; 205) 'if let... }': () |
56 | [165; 170) '[val]': {unknown} | 56 | [165; 170) '[val]': [{unknown}] |
57 | [173; 176) 'opt': {unknown} | 57 | [166; 169) 'val': {unknown} |
58 | [173; 176) 'opt': [{unknown}] | ||
58 | [177; 205) '{ ... }': () | 59 | [177; 205) '{ ... }': () |
59 | [191; 192) 'h': {unknown} | 60 | [191; 192) 'h': {unknown} |
60 | [195; 198) 'val': {unknown} | 61 | [195; 198) 'val': {unknown} |
@@ -137,6 +138,94 @@ fn test() { | |||
137 | } | 138 | } |
138 | 139 | ||
139 | #[test] | 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 | |||
228 | #[test] | ||
140 | fn infer_adt_pattern() { | 229 | fn infer_adt_pattern() { |
141 | assert_snapshot!( | 230 | assert_snapshot!( |
142 | infer(r#" | 231 | infer(r#" |