aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/_match.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/_match.rs')
-rw-r--r--crates/ra_hir_ty/src/_match.rs68
1 files changed, 41 insertions, 27 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index 779e78574..3e6e1e333 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(
573 matrix: &Matrix, 573 matrix: &Matrix,
574 v: &PatStack, 574 v: &PatStack,
575) -> MatchCheckResult<Usefulness> { 575) -> MatchCheckResult<Usefulness> {
576 // Handle the special case of enums with no variants. In that case, no match 576 // Handle two special cases:
577 // arm is useful. 577 // - enum with no variants
578 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) = 578 // - `!` type
579 cx.infer[cx.match_expr].strip_references() 579 // In those cases, no match arm is useful.
580 { 580 match cx.infer[cx.match_expr].strip_references() {
581 if cx.db.enum_data(*enum_id).variants.is_empty() { 581 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => {
582 if cx.db.enum_data(*enum_id).variants.is_empty() {
583 return Ok(Usefulness::NotUseful);
584 }
585 }
586 Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => {
582 return Ok(Usefulness::NotUseful); 587 return Ok(Usefulness::NotUseful);
583 } 588 }
589 _ => (),
584 } 590 }
585 591
586 if v.is_empty() { 592 if v.is_empty() {
@@ -1918,6 +1924,17 @@ mod tests {
1918 } 1924 }
1919 1925
1920 #[test] 1926 #[test]
1927 fn type_never() {
1928 let content = r"
1929 fn test_fn(never: !) {
1930 match never {}
1931 }
1932 ";
1933
1934 check_no_diagnostic(content);
1935 }
1936
1937 #[test]
1921 fn enum_never_ref() { 1938 fn enum_never_ref() {
1922 let content = r" 1939 let content = r"
1923 enum Never {} 1940 enum Never {}
@@ -1929,6 +1946,23 @@ mod tests {
1929 1946
1930 check_no_diagnostic(content); 1947 check_no_diagnostic(content);
1931 } 1948 }
1949
1950 #[test]
1951 fn expr_diverges_missing_arm() {
1952 let content = r"
1953 enum Either {
1954 A,
1955 B,
1956 }
1957 fn test_fn() {
1958 match loop {} {
1959 Either::A => (),
1960 }
1961 }
1962 ";
1963
1964 check_no_diagnostic(content);
1965 }
1932} 1966}
1933 1967
1934#[cfg(test)] 1968#[cfg(test)]
@@ -1981,26 +2015,6 @@ mod false_negatives {
1981 } 2015 }
1982 2016
1983 #[test] 2017 #[test]
1984 fn expr_diverges_missing_arm() {
1985 let content = r"
1986 enum Either {
1987 A,
1988 B,
1989 }
1990 fn test_fn() {
1991 match loop {} {
1992 Either::A => (),
1993 }
1994 }
1995 ";
1996
1997 // This is a false negative.
1998 // Even though the match expression diverges, rustc fails
1999 // to compile here since `Either::B` is missing.
2000 check_no_diagnostic(content);
2001 }
2002
2003 #[test]
2004 fn expr_loop_missing_arm() { 2018 fn expr_loop_missing_arm() {
2005 let content = r" 2019 let content = r"
2006 enum Either { 2020 enum Either {
@@ -2018,7 +2032,7 @@ mod false_negatives {
2018 // We currently infer the type of `loop { break Foo::A }` to `!`, which 2032 // We currently infer the type of `loop { break Foo::A }` to `!`, which
2019 // causes us to skip the diagnostic since `Either::A` doesn't type check 2033 // causes us to skip the diagnostic since `Either::A` doesn't type check
2020 // with `!`. 2034 // with `!`.
2021 check_no_diagnostic(content); 2035 check_diagnostic(content);
2022 } 2036 }
2023 2037
2024 #[test] 2038 #[test]