diff options
author | Dawer <[email protected]> | 2021-05-19 06:57:10 +0100 |
---|---|---|
committer | Dawer <[email protected]> | 2021-05-19 07:08:59 +0100 |
commit | e2b1c69f7488b942360bb3c398a1c831510d1afc (patch) | |
tree | fa3e88ea5b1ad0ff4f5e3de535b6dc188a2f1a2c /crates | |
parent | 472317c00870c007f552cde1f3c490e04f29919a (diff) |
Check patterns for type match recursively.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/diagnostics/expr.rs | 20 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/match_check.rs | 12 |
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 | ||
500 | fn 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)] |
500 | mod tests { | 516 | mod 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#" | ||
1134 | fn 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. |