diff options
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern.rs')
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern.rs | 98 |
1 files changed, 96 insertions, 2 deletions
diff --git a/crates/hir_ty/src/diagnostics/pattern.rs b/crates/hir_ty/src/diagnostics/pattern.rs index 9f65e38d6..d98fb0867 100644 --- a/crates/hir_ty/src/diagnostics/pattern.rs +++ b/crates/hir_ty/src/diagnostics/pattern.rs | |||
@@ -239,6 +239,101 @@ impl<'a> PatCtxt<'a> { | |||
239 | } | 239 | } |
240 | } | 240 | } |
241 | 241 | ||
242 | pub(crate) trait PatternFoldable: Sized { | ||
243 | fn fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
244 | self.super_fold_with(folder) | ||
245 | } | ||
246 | |||
247 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self; | ||
248 | } | ||
249 | |||
250 | pub(crate) trait PatternFolder: Sized { | ||
251 | fn fold_pattern(&mut self, pattern: &Pat) -> Pat { | ||
252 | pattern.super_fold_with(self) | ||
253 | } | ||
254 | |||
255 | fn fold_pattern_kind(&mut self, kind: &PatKind) -> PatKind { | ||
256 | kind.super_fold_with(self) | ||
257 | } | ||
258 | } | ||
259 | |||
260 | impl<T: PatternFoldable> PatternFoldable for Box<T> { | ||
261 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
262 | let content: T = (**self).fold_with(folder); | ||
263 | Box::new(content) | ||
264 | } | ||
265 | } | ||
266 | |||
267 | impl<T: PatternFoldable> PatternFoldable for Vec<T> { | ||
268 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
269 | self.iter().map(|t| t.fold_with(folder)).collect() | ||
270 | } | ||
271 | } | ||
272 | |||
273 | impl<T: PatternFoldable> PatternFoldable for Option<T> { | ||
274 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
275 | self.as_ref().map(|t| t.fold_with(folder)) | ||
276 | } | ||
277 | } | ||
278 | |||
279 | macro_rules! clone_impls { | ||
280 | ($($ty:ty),+) => { | ||
281 | $( | ||
282 | impl PatternFoldable for $ty { | ||
283 | fn super_fold_with<F: PatternFolder>(&self, _: &mut F) -> Self { | ||
284 | Clone::clone(self) | ||
285 | } | ||
286 | } | ||
287 | )+ | ||
288 | } | ||
289 | } | ||
290 | |||
291 | clone_impls! { LocalFieldId, Ty, Substitution, EnumVariantId } | ||
292 | |||
293 | impl PatternFoldable for FieldPat { | ||
294 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
295 | FieldPat { field: self.field.fold_with(folder), pattern: self.pattern.fold_with(folder) } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | impl PatternFoldable for Pat { | ||
300 | fn fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
301 | folder.fold_pattern(self) | ||
302 | } | ||
303 | |||
304 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
305 | Pat { ty: self.ty.fold_with(folder), kind: self.kind.fold_with(folder) } | ||
306 | } | ||
307 | } | ||
308 | |||
309 | impl PatternFoldable for PatKind { | ||
310 | fn fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
311 | folder.fold_pattern_kind(self) | ||
312 | } | ||
313 | |||
314 | fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self { | ||
315 | match self { | ||
316 | PatKind::Wild => PatKind::Wild, | ||
317 | PatKind::Binding { subpattern } => { | ||
318 | PatKind::Binding { subpattern: subpattern.fold_with(folder) } | ||
319 | } | ||
320 | PatKind::Variant { substs, enum_variant, subpatterns } => PatKind::Variant { | ||
321 | substs: substs.fold_with(folder), | ||
322 | enum_variant: enum_variant.fold_with(folder), | ||
323 | subpatterns: subpatterns.fold_with(folder), | ||
324 | }, | ||
325 | PatKind::Leaf { subpatterns } => { | ||
326 | PatKind::Leaf { subpatterns: subpatterns.fold_with(folder) } | ||
327 | } | ||
328 | PatKind::Deref { subpattern } => { | ||
329 | PatKind::Deref { subpattern: subpattern.fold_with(folder) } | ||
330 | } | ||
331 | &PatKind::LiteralBool { value } => PatKind::LiteralBool { value }, | ||
332 | PatKind::Or { pats } => PatKind::Or { pats: pats.fold_with(folder) }, | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | |||
242 | #[cfg(test)] | 337 | #[cfg(test)] |
243 | mod tests { | 338 | mod tests { |
244 | use crate::diagnostics::tests::check_diagnostics; | 339 | use crate::diagnostics::tests::check_diagnostics; |
@@ -410,9 +505,8 @@ fn main() { | |||
410 | _x @ true => {} | 505 | _x @ true => {} |
411 | false => {} | 506 | false => {} |
412 | } | 507 | } |
413 | //FIXME: false negative. | ||
414 | // Binding patterns should be expanded in `usefulness::expand_pattern()` | ||
415 | match true { _x @ true => {} } | 508 | match true { _x @ true => {} } |
509 | //^^^^ Missing match arm | ||
416 | } | 510 | } |
417 | "#, | 511 | "#, |
418 | ); | 512 | ); |