aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Mcguigan <[email protected]>2020-04-15 00:06:57 +0100
committerJosh Mcguigan <[email protected]>2020-04-16 13:37:49 +0100
commit360bdf653b91f5232a5584c7f4b13960caa48dda (patch)
treedb24ae367e16cb316ffa7bccdac34afbde32ea2a
parentc82e7696e6f86cc0843c5aab9f09b5d6dd0d4bac (diff)
fix false positive for enum with no variants
-rw-r--r--crates/ra_hir_ty/src/_match.rs42
-rw-r--r--crates/ra_hir_ty/src/expr.rs2
-rw-r--r--crates/ra_hir_ty/src/lib.rs10
3 files changed, 51 insertions, 3 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index a64be9848..688026a04 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -194,9 +194,10 @@ use smallvec::{smallvec, SmallVec};
194use crate::{ 194use crate::{
195 db::HirDatabase, 195 db::HirDatabase,
196 expr::{Body, Expr, Literal, Pat, PatId}, 196 expr::{Body, Expr, Literal, Pat, PatId},
197 InferenceResult, 197 ApplicationTy, InferenceResult, Ty, TypeCtor,
198}; 198};
199use hir_def::{adt::VariantData, EnumVariantId, VariantId}; 199use hir_def::{adt::VariantData, AdtId, EnumVariantId, VariantId};
200use ra_arena::Idx;
200 201
201#[derive(Debug, Clone, Copy)] 202#[derive(Debug, Clone, Copy)]
202/// Either a pattern from the source code being analyzed, represented as 203/// Either a pattern from the source code being analyzed, represented as
@@ -512,6 +513,7 @@ pub enum Usefulness {
512} 513}
513 514
514pub struct MatchCheckCtx<'a> { 515pub struct MatchCheckCtx<'a> {
516 pub match_expr: Idx<Expr>,
515 pub body: Arc<Body>, 517 pub body: Arc<Body>,
516 pub infer: Arc<InferenceResult>, 518 pub infer: Arc<InferenceResult>,
517 pub db: &'a dyn HirDatabase, 519 pub db: &'a dyn HirDatabase,
@@ -530,6 +532,16 @@ pub(crate) fn is_useful(
530 matrix: &Matrix, 532 matrix: &Matrix,
531 v: &PatStack, 533 v: &PatStack,
532) -> MatchCheckResult<Usefulness> { 534) -> MatchCheckResult<Usefulness> {
535 // Handle the special case of enums with no variants. In that case, no match
536 // arm is useful.
537 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) =
538 cx.infer[cx.match_expr].strip_references()
539 {
540 if cx.db.enum_data(*enum_id).variants.is_empty() {
541 return Ok(Usefulness::NotUseful);
542 }
543 }
544
533 if v.is_empty() { 545 if v.is_empty() {
534 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful }; 546 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
535 547
@@ -1618,6 +1630,32 @@ mod tests {
1618 1630
1619 check_no_diagnostic(content); 1631 check_no_diagnostic(content);
1620 } 1632 }
1633
1634 #[test]
1635 fn enum_never() {
1636 let content = r"
1637 enum Never {}
1638
1639 fn test_fn(never: Never) {
1640 match never {}
1641 }
1642 ";
1643
1644 check_no_diagnostic(content);
1645 }
1646
1647 #[test]
1648 fn enum_never_ref() {
1649 let content = r"
1650 enum Never {}
1651
1652 fn test_fn(never: &Never) {
1653 match never {}
1654 }
1655 ";
1656
1657 check_no_diagnostic(content);
1658 }
1621} 1659}
1622 1660
1623#[cfg(test)] 1661#[cfg(test)]
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index 21abbcf1e..fd59f4320 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -156,7 +156,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
156 None => return, 156 None => return,
157 }; 157 };
158 158
159 let cx = MatchCheckCtx { body, infer: infer.clone(), db }; 159 let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db };
160 let pats = arms.iter().map(|arm| arm.pat); 160 let pats = arms.iter().map(|arm| arm.pat);
161 161
162 let mut seen = Matrix::empty(); 162 let mut seen = Matrix::empty();
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 18f74d3b1..2677f3af2 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -680,6 +680,16 @@ impl Ty {
680 } 680 }
681 } 681 }
682 682
683 pub fn strip_references(&self) -> &Ty {
684 let mut t: &Ty = self;
685
686 while let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_mutability), parameters }) = t {
687 t = parameters.as_single();
688 }
689
690 t
691 }
692
683 pub fn as_adt(&self) -> Option<(AdtId, &Substs)> { 693 pub fn as_adt(&self) -> Option<(AdtId, &Substs)> {
684 match self { 694 match self {
685 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { 695 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => {