From 7d675eda80c5f1eb4a9fe7d374023d71721bf2f1 Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Mon, 10 May 2021 22:40:35 +0500 Subject: Don't panic on a pattern of unresolved ADT variant. --- crates/hir_ty/src/diagnostics/match_check.rs | 1 + crates/hir_ty/src/diagnostics/pattern.rs | 63 ++++++---------------------- 2 files changed, 14 insertions(+), 50 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index e8dd669bf..52e9a5b1b 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -1357,6 +1357,7 @@ fn enum_(never: Never) { } fn enum_ref(never: &Never) { match never {} + //^^^^^ Missing match arm } fn bang(never: !) { match never {} diff --git a/crates/hir_ty/src/diagnostics/pattern.rs b/crates/hir_ty/src/diagnostics/pattern.rs index 85c01b178..4f88dfe60 100644 --- a/crates/hir_ty/src/diagnostics/pattern.rs +++ b/crates/hir_ty/src/diagnostics/pattern.rs @@ -21,6 +21,7 @@ pub(crate) type PatId = Idx; #[derive(Clone, Debug)] pub(crate) enum PatternError { Unimplemented, + UnresolvedVariant, } #[derive(Clone, Debug, PartialEq)] @@ -103,6 +104,7 @@ impl<'a> PatCtxt<'a> { fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat { let ty = &self.infer[pat]; + let variant = self.infer.variant_resolution_for_pat(pat); let kind = match self.body[pat] { hir_def::expr::Pat::Wild => PatKind::Wild, @@ -126,21 +128,14 @@ impl<'a> PatCtxt<'a> { PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) } } - hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } => { - let variant_data = match self.infer.variant_resolution_for_pat(pat) { - Some(variant_id) => variant_id.variant_data(self.db.upcast()), - None => panic!("tuple struct pattern not applied to an ADT {:?}", ty), - }; - let subpatterns = - self.lower_tuple_subpats(args, variant_data.fields().len(), ellipsis); + hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => { + let expected_len = variant.unwrap().variant_data(self.db.upcast()).fields().len(); + let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis); self.lower_variant_or_leaf(pat, ty, subpatterns) } - hir_def::expr::Pat::Record { ref args, .. } => { - let variant_data = match self.infer.variant_resolution_for_pat(pat) { - Some(variant_id) => variant_id.variant_data(self.db.upcast()), - None => panic!("record pattern not applied to an ADT {:?}", ty), - }; + hir_def::expr::Pat::Record { ref args, .. } if variant.is_some() => { + let variant_data = variant.unwrap().variant_data(self.db.upcast()); let subpatterns = args .iter() .map(|field| FieldPat { @@ -151,6 +146,10 @@ impl<'a> PatCtxt<'a> { .collect(); self.lower_variant_or_leaf(pat, ty, subpatterns) } + hir_def::expr::Pat::TupleStruct { .. } | hir_def::expr::Pat::Record { .. } => { + self.errors.push(PatternError::UnresolvedVariant); + PatKind::Wild + } hir_def::expr::Pat::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) }, @@ -208,7 +207,7 @@ impl<'a> PatCtxt<'a> { } } None => { - self.errors.push(PatternError::Unimplemented); + self.errors.push(PatternError::UnresolvedVariant); PatKind::Wild } }; @@ -223,7 +222,7 @@ impl<'a> PatCtxt<'a> { match self.infer.variant_resolution_for_pat(pat) { Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())), None => { - self.errors.push(PatternError::Unimplemented); + self.errors.push(PatternError::UnresolvedVariant); pat_from_kind(PatKind::Wild) } } @@ -510,40 +509,4 @@ fn main() { "#, ); } - - /// These failing tests are narrowed down from "hir_ty::diagnostics::match_check::tests" - // TODO fix - mod failing { - use super::*; - - #[test] - fn never() { - check_diagnostics( - r#" -enum Never {} - -fn enum_ref(never: &Never) { - match never {} -} -"#, - ); - } - - #[test] - fn unknown_type() { - check_diagnostics( - r#" -enum Option { Some(T), None } - -fn main() { - // `Never` is deliberately not defined so that it's an uninferred type. - match Option::::None { - None => {} - Some(never) => {} - } -} -"#, - ); - } - } } -- cgit v1.2.3