aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorDawer <[email protected]>2021-05-19 06:57:10 +0100
committerDawer <[email protected]>2021-05-19 07:08:59 +0100
commite2b1c69f7488b942360bb3c398a1c831510d1afc (patch)
treefa3e88ea5b1ad0ff4f5e3de535b6dc188a2f1a2c /crates
parent472317c00870c007f552cde1f3c490e04f29919a (diff)
Check patterns for type match recursively.
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs20
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs12
2 files changed, 30 insertions, 2 deletions
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index a50ad6b09..b9a69b79c 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -311,11 +311,12 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
311 // necessary. 311 // necessary.
312 // 312 //
313 // FIXME we should use the type checker for this. 313 // FIXME we should use the type checker for this.
314 if pat_ty == match_expr_ty 314 if (pat_ty == match_expr_ty
315 || match_expr_ty 315 || match_expr_ty
316 .as_reference() 316 .as_reference()
317 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty) 317 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
318 .unwrap_or(false) 318 .unwrap_or(false))
319 && types_of_subpatterns_do_match(pat, &cx.body, &infer)
319 { 320 {
320 // If we had a NotUsefulMatchArm diagnostic, we could 321 // If we had a NotUsefulMatchArm diagnostic, we could
321 // check the usefulness of each pattern as we added it 322 // check the usefulness of each pattern as we added it
@@ -496,6 +497,21 @@ pub fn record_pattern_missing_fields(
496 Some((variant_def, missed_fields, exhaustive)) 497 Some((variant_def, missed_fields, exhaustive))
497} 498}
498 499
500fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResult) -> bool {
501 fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) {
502 match infer.type_mismatch_for_pat(pat) {
503 Some(_) => *has_type_mismatches = true,
504 None => {
505 body[pat].walk_child_pats(|subpat| walk(subpat, body, infer, has_type_mismatches))
506 }
507 }
508 }
509
510 let mut has_type_mismatches = false;
511 walk(pat, body, infer, &mut has_type_mismatches);
512 !has_type_mismatches
513}
514
499#[cfg(test)] 515#[cfg(test)]
500mod tests { 516mod tests {
501 use crate::diagnostics::tests::check_diagnostics; 517 use crate::diagnostics::tests::check_diagnostics;
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 6ee0529c6..e8dd669bf 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -1128,6 +1128,18 @@ fn main() {
1128 } 1128 }
1129 1129
1130 #[test] 1130 #[test]
1131 fn mismatched_types_in_or_patterns() {
1132 check_diagnostics(
1133 r#"
1134fn main() {
1135 match false { true | () => {} }
1136 match (false,) { (true | (),) => {} }
1137}
1138"#,
1139 );
1140 }
1141
1142 #[test]
1131 fn malformed_match_arm_tuple_enum_missing_pattern() { 1143 fn malformed_match_arm_tuple_enum_missing_pattern() {
1132 // We are testing to be sure we don't panic here when the match 1144 // We are testing to be sure we don't panic here when the match
1133 // arm `Either::B` is missing its pattern. 1145 // arm `Either::B` is missing its pattern.