Don't panic on a pattern of unresolved ADT variant.

This commit is contained in:
Dawer 2021-05-10 22:40:35 +05:00
parent 466345ca81
commit 7d675eda80
2 changed files with 14 additions and 50 deletions

View File

@ -1357,6 +1357,7 @@ fn enum_(never: Never) {
} }
fn enum_ref(never: &Never) { fn enum_ref(never: &Never) {
match never {} match never {}
//^^^^^ Missing match arm
} }
fn bang(never: !) { fn bang(never: !) {
match never {} match never {}

View File

@ -21,6 +21,7 @@ pub(crate) type PatId = Idx<Pat>;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) enum PatternError { pub(crate) enum PatternError {
Unimplemented, Unimplemented,
UnresolvedVariant,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -103,6 +104,7 @@ impl<'a> PatCtxt<'a> {
fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat { fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat {
let ty = &self.infer[pat]; let ty = &self.infer[pat];
let variant = self.infer.variant_resolution_for_pat(pat);
let kind = match self.body[pat] { let kind = match self.body[pat] {
hir_def::expr::Pat::Wild => PatKind::Wild, hir_def::expr::Pat::Wild => PatKind::Wild,
@ -126,21 +128,14 @@ impl<'a> PatCtxt<'a> {
PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) } PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) }
} }
hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } => { hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => {
let variant_data = match self.infer.variant_resolution_for_pat(pat) { let expected_len = variant.unwrap().variant_data(self.db.upcast()).fields().len();
Some(variant_id) => variant_id.variant_data(self.db.upcast()), let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis);
None => panic!("tuple struct pattern not applied to an ADT {:?}", ty),
};
let subpatterns =
self.lower_tuple_subpats(args, variant_data.fields().len(), ellipsis);
self.lower_variant_or_leaf(pat, ty, subpatterns) self.lower_variant_or_leaf(pat, ty, subpatterns)
} }
hir_def::expr::Pat::Record { ref args, .. } => { hir_def::expr::Pat::Record { ref args, .. } if variant.is_some() => {
let variant_data = match self.infer.variant_resolution_for_pat(pat) { let variant_data = variant.unwrap().variant_data(self.db.upcast());
Some(variant_id) => variant_id.variant_data(self.db.upcast()),
None => panic!("record pattern not applied to an ADT {:?}", ty),
};
let subpatterns = args let subpatterns = args
.iter() .iter()
.map(|field| FieldPat { .map(|field| FieldPat {
@ -151,6 +146,10 @@ impl<'a> PatCtxt<'a> {
.collect(); .collect();
self.lower_variant_or_leaf(pat, ty, subpatterns) 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) }, hir_def::expr::Pat::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) },
@ -208,7 +207,7 @@ impl<'a> PatCtxt<'a> {
} }
} }
None => { None => {
self.errors.push(PatternError::Unimplemented); self.errors.push(PatternError::UnresolvedVariant);
PatKind::Wild PatKind::Wild
} }
}; };
@ -223,7 +222,7 @@ impl<'a> PatCtxt<'a> {
match self.infer.variant_resolution_for_pat(pat) { match self.infer.variant_resolution_for_pat(pat) {
Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())), Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())),
None => { None => {
self.errors.push(PatternError::Unimplemented); self.errors.push(PatternError::UnresolvedVariant);
pat_from_kind(PatKind::Wild) 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<T> { Some(T), None }
fn main() {
// `Never` is deliberately not defined so that it's an uninferred type.
match Option::<Never>::None {
None => {}
Some(never) => {}
}
}
"#,
);
}
}
} }