Skip to content

Commit e9d3565

Browse files
committed
Auto merge of rust-lang#16502 - davidsemakula:unnecessary-else-diagnostic, r=Veykril
feat: Add "unnecessary else" diagnostic and fix Fixes rust-lang#9457
2 parents 82674e2 + d7a0302 commit e9d3565

File tree

6 files changed

+447
-4
lines changed

6 files changed

+447
-4
lines changed

crates/hir-ty/src/diagnostics/expr.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::{
2727

2828
pub(crate) use hir_def::{
2929
body::Body,
30-
hir::{Expr, ExprId, MatchArm, Pat, PatId},
30+
hir::{Expr, ExprId, MatchArm, Pat, PatId, Statement},
3131
LocalFieldId, VariantId,
3232
};
3333

@@ -44,6 +44,9 @@ pub enum BodyValidationDiagnostic {
4444
match_expr: ExprId,
4545
uncovered_patterns: String,
4646
},
47+
RemoveUnnecessaryElse {
48+
if_expr: ExprId,
49+
},
4750
}
4851

4952
impl BodyValidationDiagnostic {
@@ -90,6 +93,9 @@ impl ExprValidator {
9093
Expr::Call { .. } | Expr::MethodCall { .. } => {
9194
self.validate_call(db, id, expr, &mut filter_map_next_checker);
9295
}
96+
Expr::If { .. } => {
97+
self.check_for_unnecessary_else(id, expr, &body);
98+
}
9399
_ => {}
94100
}
95101
}
@@ -237,6 +243,27 @@ impl ExprValidator {
237243
}
238244
pattern
239245
}
246+
247+
fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, body: &Body) {
248+
if let Expr::If { condition: _, then_branch, else_branch } = expr {
249+
if else_branch.is_none() {
250+
return;
251+
}
252+
if let Expr::Block { statements, tail, .. } = &body.exprs[*then_branch] {
253+
let last_then_expr = tail.or_else(|| match statements.last()? {
254+
Statement::Expr { expr, .. } => Some(*expr),
255+
_ => None,
256+
});
257+
if let Some(last_then_expr) = last_then_expr {
258+
let last_then_expr_ty = &self.infer[last_then_expr];
259+
if last_then_expr_ty.is_never() {
260+
self.diagnostics
261+
.push(BodyValidationDiagnostic::RemoveUnnecessaryElse { if_expr: id })
262+
}
263+
}
264+
}
265+
}
266+
}
240267
}
241268

242269
struct FilterMapNextChecker {

crates/hir/src/diagnostics.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ diagnostics![
6868
PrivateAssocItem,
6969
PrivateField,
7070
ReplaceFilterMapNextWithFindMap,
71+
RemoveUnnecessaryElse,
7172
TraitImplIncorrectSafety,
7273
TraitImplMissingAssocItems,
7374
TraitImplOrphan,
@@ -342,6 +343,11 @@ pub struct TraitImplRedundantAssocItems {
342343
pub assoc_item: (Name, AssocItem),
343344
}
344345

346+
#[derive(Debug)]
347+
pub struct RemoveUnnecessaryElse {
348+
pub if_expr: InFile<AstPtr<ast::IfExpr>>,
349+
}
350+
345351
impl AnyDiagnostic {
346352
pub(crate) fn body_validation_diagnostic(
347353
db: &dyn HirDatabase,
@@ -444,6 +450,16 @@ impl AnyDiagnostic {
444450
Err(SyntheticSyntax) => (),
445451
}
446452
}
453+
BodyValidationDiagnostic::RemoveUnnecessaryElse { if_expr } => {
454+
if let Ok(source_ptr) = source_map.expr_syntax(if_expr) {
455+
if let Some(ptr) = source_ptr.value.cast::<ast::IfExpr>() {
456+
return Some(
457+
RemoveUnnecessaryElse { if_expr: InFile::new(source_ptr.file_id, ptr) }
458+
.into(),
459+
);
460+
}
461+
}
462+
}
447463
}
448464
None
449465
}

crates/ide-diagnostics/src/handlers/mutability_errors.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken
8686

8787
#[cfg(test)]
8888
mod tests {
89-
use crate::tests::{check_diagnostics, check_fix};
89+
use crate::tests::{check_diagnostics, check_diagnostics_with_disabled, check_fix};
9090

9191
#[test]
9292
fn unused_mut_simple() {
@@ -428,7 +428,7 @@ fn main() {
428428
}
429429
"#,
430430
);
431-
check_diagnostics(
431+
check_diagnostics_with_disabled(
432432
r#"
433433
enum X {}
434434
fn g() -> X {
@@ -448,8 +448,9 @@ fn main(b: bool) {
448448
&mut x;
449449
}
450450
"#,
451+
std::iter::once("remove-unnecessary-else".to_string()),
451452
);
452-
check_diagnostics(
453+
check_diagnostics_with_disabled(
453454
r#"
454455
fn main(b: bool) {
455456
if b {
@@ -462,6 +463,7 @@ fn main(b: bool) {
462463
&mut x;
463464
}
464465
"#,
466+
std::iter::once("remove-unnecessary-else".to_string()),
465467
);
466468
}
467469

0 commit comments

Comments
 (0)