diff options
author | Dawer <[email protected]> | 2021-05-10 18:40:35 +0100 |
---|---|---|
committer | Dawer <[email protected]> | 2021-05-31 20:08:43 +0100 |
commit | 7d675eda80c5f1eb4a9fe7d374023d71721bf2f1 (patch) | |
tree | c6a3e1bf3709c63d4451a52d0c110340b0665234 /crates/hir_ty/src/diagnostics | |
parent | 466345ca81c9f8a17347671ca27856eb963858f4 (diff) |
Don't panic on a pattern of unresolved ADT variant.
Diffstat (limited to 'crates/hir_ty/src/diagnostics')
-rw-r--r-- | crates/hir_ty/src/diagnostics/match_check.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern.rs | 63 |
2 files changed, 14 insertions, 50 deletions
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) { | |||
1357 | } | 1357 | } |
1358 | fn enum_ref(never: &Never) { | 1358 | fn enum_ref(never: &Never) { |
1359 | match never {} | 1359 | match never {} |
1360 | //^^^^^ Missing match arm | ||
1360 | } | 1361 | } |
1361 | fn bang(never: !) { | 1362 | fn bang(never: !) { |
1362 | match never {} | 1363 | 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<Pat>; | |||
21 | #[derive(Clone, Debug)] | 21 | #[derive(Clone, Debug)] |
22 | pub(crate) enum PatternError { | 22 | pub(crate) enum PatternError { |
23 | Unimplemented, | 23 | Unimplemented, |
24 | UnresolvedVariant, | ||
24 | } | 25 | } |
25 | 26 | ||
26 | #[derive(Clone, Debug, PartialEq)] | 27 | #[derive(Clone, Debug, PartialEq)] |
@@ -103,6 +104,7 @@ impl<'a> PatCtxt<'a> { | |||
103 | 104 | ||
104 | fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat { | 105 | fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat { |
105 | let ty = &self.infer[pat]; | 106 | let ty = &self.infer[pat]; |
107 | let variant = self.infer.variant_resolution_for_pat(pat); | ||
106 | 108 | ||
107 | let kind = match self.body[pat] { | 109 | let kind = match self.body[pat] { |
108 | hir_def::expr::Pat::Wild => PatKind::Wild, | 110 | hir_def::expr::Pat::Wild => PatKind::Wild, |
@@ -126,21 +128,14 @@ impl<'a> PatCtxt<'a> { | |||
126 | PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) } | 128 | PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) } |
127 | } | 129 | } |
128 | 130 | ||
129 | hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } => { | 131 | hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => { |
130 | let variant_data = match self.infer.variant_resolution_for_pat(pat) { | 132 | let expected_len = variant.unwrap().variant_data(self.db.upcast()).fields().len(); |
131 | Some(variant_id) => variant_id.variant_data(self.db.upcast()), | 133 | let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis); |
132 | None => panic!("tuple struct pattern not applied to an ADT {:?}", ty), | ||
133 | }; | ||
134 | let subpatterns = | ||
135 | self.lower_tuple_subpats(args, variant_data.fields().len(), ellipsis); | ||
136 | self.lower_variant_or_leaf(pat, ty, subpatterns) | 134 | self.lower_variant_or_leaf(pat, ty, subpatterns) |
137 | } | 135 | } |
138 | 136 | ||
139 | hir_def::expr::Pat::Record { ref args, .. } => { | 137 | hir_def::expr::Pat::Record { ref args, .. } if variant.is_some() => { |
140 | let variant_data = match self.infer.variant_resolution_for_pat(pat) { | 138 | let variant_data = variant.unwrap().variant_data(self.db.upcast()); |
141 | Some(variant_id) => variant_id.variant_data(self.db.upcast()), | ||
142 | None => panic!("record pattern not applied to an ADT {:?}", ty), | ||
143 | }; | ||
144 | let subpatterns = args | 139 | let subpatterns = args |
145 | .iter() | 140 | .iter() |
146 | .map(|field| FieldPat { | 141 | .map(|field| FieldPat { |
@@ -151,6 +146,10 @@ impl<'a> PatCtxt<'a> { | |||
151 | .collect(); | 146 | .collect(); |
152 | self.lower_variant_or_leaf(pat, ty, subpatterns) | 147 | self.lower_variant_or_leaf(pat, ty, subpatterns) |
153 | } | 148 | } |
149 | hir_def::expr::Pat::TupleStruct { .. } | hir_def::expr::Pat::Record { .. } => { | ||
150 | self.errors.push(PatternError::UnresolvedVariant); | ||
151 | PatKind::Wild | ||
152 | } | ||
154 | 153 | ||
155 | hir_def::expr::Pat::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) }, | 154 | hir_def::expr::Pat::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) }, |
156 | 155 | ||
@@ -208,7 +207,7 @@ impl<'a> PatCtxt<'a> { | |||
208 | } | 207 | } |
209 | } | 208 | } |
210 | None => { | 209 | None => { |
211 | self.errors.push(PatternError::Unimplemented); | 210 | self.errors.push(PatternError::UnresolvedVariant); |
212 | PatKind::Wild | 211 | PatKind::Wild |
213 | } | 212 | } |
214 | }; | 213 | }; |
@@ -223,7 +222,7 @@ impl<'a> PatCtxt<'a> { | |||
223 | match self.infer.variant_resolution_for_pat(pat) { | 222 | match self.infer.variant_resolution_for_pat(pat) { |
224 | Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())), | 223 | Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())), |
225 | None => { | 224 | None => { |
226 | self.errors.push(PatternError::Unimplemented); | 225 | self.errors.push(PatternError::UnresolvedVariant); |
227 | pat_from_kind(PatKind::Wild) | 226 | pat_from_kind(PatKind::Wild) |
228 | } | 227 | } |
229 | } | 228 | } |
@@ -510,40 +509,4 @@ fn main() { | |||
510 | "#, | 509 | "#, |
511 | ); | 510 | ); |
512 | } | 511 | } |
513 | |||
514 | /// These failing tests are narrowed down from "hir_ty::diagnostics::match_check::tests" | ||
515 | // TODO fix | ||
516 | mod failing { | ||
517 | use super::*; | ||
518 | |||
519 | #[test] | ||
520 | fn never() { | ||
521 | check_diagnostics( | ||
522 | r#" | ||
523 | enum Never {} | ||
524 | |||
525 | fn enum_ref(never: &Never) { | ||
526 | match never {} | ||
527 | } | ||
528 | "#, | ||
529 | ); | ||
530 | } | ||
531 | |||
532 | #[test] | ||
533 | fn unknown_type() { | ||
534 | check_diagnostics( | ||
535 | r#" | ||
536 | enum Option<T> { Some(T), None } | ||
537 | |||
538 | fn main() { | ||
539 | // `Never` is deliberately not defined so that it's an uninferred type. | ||
540 | match Option::<Never>::None { | ||
541 | None => {} | ||
542 | Some(never) => {} | ||
543 | } | ||
544 | } | ||
545 | "#, | ||
546 | ); | ||
547 | } | ||
548 | } | ||
549 | } | 512 | } |