aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorDawer <[email protected]>2021-05-10 18:40:35 +0100
committerDawer <[email protected]>2021-05-31 20:08:43 +0100
commit7d675eda80c5f1eb4a9fe7d374023d71721bf2f1 (patch)
treec6a3e1bf3709c63d4451a52d0c110340b0665234 /crates/hir_ty
parent466345ca81c9f8a17347671ca27856eb963858f4 (diff)
Don't panic on a pattern of unresolved ADT variant.
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs1
-rw-r--r--crates/hir_ty/src/diagnostics/pattern.rs63
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}
1358fn enum_ref(never: &Never) { 1358fn enum_ref(never: &Never) {
1359 match never {} 1359 match never {}
1360 //^^^^^ Missing match arm
1360} 1361}
1361fn bang(never: !) { 1362fn 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)]
22pub(crate) enum PatternError { 22pub(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#"
523enum Never {}
524
525fn enum_ref(never: &Never) {
526 match never {}
527}
528"#,
529 );
530 }
531
532 #[test]
533 fn unknown_type() {
534 check_diagnostics(
535 r#"
536enum Option<T> { Some(T), None }
537
538fn 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}