From 7c94fa7d01f264e5268ab5f57519f071c00a6579 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Wed, 6 May 2020 17:45:47 +0300 Subject: Fix usefulness check for never type --- crates/ra_hir_ty/src/_match.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty/src/_match.rs') diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs index 779e78574..149f65042 100644 --- a/crates/ra_hir_ty/src/_match.rs +++ b/crates/ra_hir_ty/src/_match.rs @@ -573,14 +573,20 @@ pub(crate) fn is_useful( matrix: &Matrix, v: &PatStack, ) -> MatchCheckResult { - // Handle the special case of enums with no variants. In that case, no match - // arm is useful. - if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) = - cx.infer[cx.match_expr].strip_references() - { - if cx.db.enum_data(*enum_id).variants.is_empty() { + // Handle two special cases: + // - enum with no variants + // - `!` type + // In those cases, no match arm is useful. + match cx.infer[cx.match_expr].strip_references() { + Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => { + if cx.db.enum_data(*enum_id).variants.is_empty() { + return Ok(Usefulness::NotUseful); + } + } + Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => { return Ok(Usefulness::NotUseful); } + _ => (), } if v.is_empty() { @@ -1917,6 +1923,17 @@ mod tests { check_no_diagnostic(content); } + #[test] + fn type_never() { + let content = r" + fn test_fn(never: !) { + match never {} + } + "; + + check_no_diagnostic(content); + } + #[test] fn enum_never_ref() { let content = r" -- cgit v1.2.3 From 6e36ad3d910ebec5af5f4f208b0f98c613687c41 Mon Sep 17 00:00:00 2001 From: Roland Ruckerbauer Date: Tue, 19 May 2020 21:18:43 +0200 Subject: Move false negative expr_diverges_missing_arm() to working tests --- crates/ra_hir_ty/src/_match.rs | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'crates/ra_hir_ty/src/_match.rs') diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs index 149f65042..3e6e1e333 100644 --- a/crates/ra_hir_ty/src/_match.rs +++ b/crates/ra_hir_ty/src/_match.rs @@ -1946,6 +1946,23 @@ mod tests { check_no_diagnostic(content); } + + #[test] + fn expr_diverges_missing_arm() { + let content = r" + enum Either { + A, + B, + } + fn test_fn() { + match loop {} { + Either::A => (), + } + } + "; + + check_no_diagnostic(content); + } } #[cfg(test)] @@ -1997,26 +2014,6 @@ mod false_negatives { check_no_diagnostic(content); } - #[test] - fn expr_diverges_missing_arm() { - let content = r" - enum Either { - A, - B, - } - fn test_fn() { - match loop {} { - Either::A => (), - } - } - "; - - // This is a false negative. - // Even though the match expression diverges, rustc fails - // to compile here since `Either::B` is missing. - check_no_diagnostic(content); - } - #[test] fn expr_loop_missing_arm() { let content = r" @@ -2035,7 +2032,7 @@ mod false_negatives { // We currently infer the type of `loop { break Foo::A }` to `!`, which // causes us to skip the diagnostic since `Either::A` doesn't type check // with `!`. - check_no_diagnostic(content); + check_diagnostic(content); } #[test] -- cgit v1.2.3