From e2b1c69f7488b942360bb3c398a1c831510d1afc Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Wed, 19 May 2021 10:57:10 +0500 Subject: Check patterns for type match recursively. --- crates/hir_ty/src/diagnostics/expr.rs | 20 ++++++++++++++++++-- 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> { // necessary. // // FIXME we should use the type checker for this. - if pat_ty == match_expr_ty + if (pat_ty == match_expr_ty || match_expr_ty .as_reference() .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty) - .unwrap_or(false) + .unwrap_or(false)) + && types_of_subpatterns_do_match(pat, &cx.body, &infer) { // If we had a NotUsefulMatchArm diagnostic, we could // check the usefulness of each pattern as we added it @@ -496,6 +497,21 @@ pub fn record_pattern_missing_fields( Some((variant_def, missed_fields, exhaustive)) } +fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResult) -> bool { + fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) { + match infer.type_mismatch_for_pat(pat) { + Some(_) => *has_type_mismatches = true, + None => { + body[pat].walk_child_pats(|subpat| walk(subpat, body, infer, has_type_mismatches)) + } + } + } + + let mut has_type_mismatches = false; + walk(pat, body, infer, &mut has_type_mismatches); + !has_type_mismatches +} + #[cfg(test)] mod tests { 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 @@ -1127,6 +1127,18 @@ fn main() { ); } + #[test] + fn mismatched_types_in_or_patterns() { + check_diagnostics( + r#" +fn main() { + match false { true | () => {} } + match (false,) { (true | (),) => {} } +} +"#, + ); + } + #[test] fn malformed_match_arm_tuple_enum_missing_pattern() { // We are testing to be sure we don't panic here when the match -- cgit v1.2.3