mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
Merge #3979
3979: fix missing match arm false positive for enum with no variants r=flodiebold a=JoshMcguigan fixes #3974 Co-authored-by: Josh Mcguigan <joshmcg88@gmail.com>
This commit is contained in:
commit
0390d62168
3 changed files with 51 additions and 3 deletions
|
@ -194,9 +194,10 @@ use smallvec::{smallvec, SmallVec};
|
|||
use crate::{
|
||||
db::HirDatabase,
|
||||
expr::{Body, Expr, Literal, Pat, PatId},
|
||||
InferenceResult,
|
||||
ApplicationTy, InferenceResult, Ty, TypeCtor,
|
||||
};
|
||||
use hir_def::{adt::VariantData, EnumVariantId, VariantId};
|
||||
use hir_def::{adt::VariantData, AdtId, EnumVariantId, VariantId};
|
||||
use ra_arena::Idx;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// Either a pattern from the source code being analyzed, represented as
|
||||
|
@ -512,6 +513,7 @@ pub enum Usefulness {
|
|||
}
|
||||
|
||||
pub struct MatchCheckCtx<'a> {
|
||||
pub match_expr: Idx<Expr>,
|
||||
pub body: Arc<Body>,
|
||||
pub infer: Arc<InferenceResult>,
|
||||
pub db: &'a dyn HirDatabase,
|
||||
|
@ -530,6 +532,16 @@ pub(crate) fn is_useful(
|
|||
matrix: &Matrix,
|
||||
v: &PatStack,
|
||||
) -> MatchCheckResult<Usefulness> {
|
||||
// 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() {
|
||||
return Ok(Usefulness::NotUseful);
|
||||
}
|
||||
}
|
||||
|
||||
if v.is_empty() {
|
||||
let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
|
||||
|
||||
|
@ -1618,6 +1630,32 @@ mod tests {
|
|||
|
||||
check_no_diagnostic(content);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_never() {
|
||||
let content = r"
|
||||
enum Never {}
|
||||
|
||||
fn test_fn(never: Never) {
|
||||
match never {}
|
||||
}
|
||||
";
|
||||
|
||||
check_no_diagnostic(content);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_never_ref() {
|
||||
let content = r"
|
||||
enum Never {}
|
||||
|
||||
fn test_fn(never: &Never) {
|
||||
match never {}
|
||||
}
|
||||
";
|
||||
|
||||
check_no_diagnostic(content);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -156,7 +156,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let cx = MatchCheckCtx { body, infer: infer.clone(), db };
|
||||
let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db };
|
||||
let pats = arms.iter().map(|arm| arm.pat);
|
||||
|
||||
let mut seen = Matrix::empty();
|
||||
|
|
|
@ -680,6 +680,16 @@ impl Ty {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn strip_references(&self) -> &Ty {
|
||||
let mut t: &Ty = self;
|
||||
|
||||
while let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_mutability), parameters }) = t {
|
||||
t = parameters.as_single();
|
||||
}
|
||||
|
||||
t
|
||||
}
|
||||
|
||||
pub fn as_adt(&self) -> Option<(AdtId, &Substs)> {
|
||||
match self {
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => {
|
||||
|
|
Loading…
Reference in a new issue