Skip to content

Commit

Permalink
Auto merge of #13324 - WeiTheShinobi:single_match, r=dswij
Browse files Browse the repository at this point in the history
[`single_match`, `single_match_else`] fix suggestion when match irrefutable

fixes #13012

changelog:[`single_match`, `single_match_else`]: fix suggestion when `match` irrefutable
  • Loading branch information
bors committed Sep 8, 2024
2 parents 41dc86d + e3ca249 commit bcf528b
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 4 deletions.
27 changes: 25 additions & 2 deletions clippy_lints/src/matches/single_match.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{expr_block, snippet, SpanRangeExt};
use clippy_utils::source::{expr_block, snippet, snippet_block_with_context, SpanRangeExt};
use clippy_utils::ty::implements_trait;
use clippy_utils::{
is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
Expand All @@ -9,7 +9,7 @@ use rustc_arena::DroplessArena;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_pat, Visitor};
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind, QPath};
use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
use rustc_span::{sym, Span};
Expand Down Expand Up @@ -91,6 +91,29 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
});

if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
let msg = "this pattern is irrefutable, `match` is useless";
let (sugg, help) = if is_unit_expr(arm.body) {
(String::new(), "`match` expression can be removed")
} else {
let mut sugg = snippet_block_with_context(cx, arm.body.span, ctxt, "..", Some(expr.span), &mut app)
.0
.to_string();
if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
&& let StmtKind::Expr(_) = stmt.kind
&& match arm.body.kind {
ExprKind::Block(block, _) => block.span.from_expansion(),
_ => true,
}
{
sugg.push(';');
}
(sugg, "try")
};
span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg.to_string(), app);
return;
}

let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
&& let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))
Expand Down
24 changes: 24 additions & 0 deletions tests/ui/single_match.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,27 @@ fn issue11365() {

if let Some(A | B) = &Some(A) { println!() }
}

#[derive(Eq, PartialEq)]
pub struct Data([u8; 4]);

const DATA: Data = Data([1, 2, 3, 4]);
const CONST_I32: i32 = 1;

fn irrefutable_match() {
println!();

println!();

let i = 0;
{
let a = 1;
let b = 2;
}





println!()
}
42 changes: 42 additions & 0 deletions tests/ui/single_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,45 @@ fn issue11365() {
None | Some(_) => {},
}
}

#[derive(Eq, PartialEq)]
pub struct Data([u8; 4]);

const DATA: Data = Data([1, 2, 3, 4]);
const CONST_I32: i32 = 1;

fn irrefutable_match() {
match DATA {
DATA => println!(),
_ => {},
}

match CONST_I32 {
CONST_I32 => println!(),
_ => {},
}

let i = 0;
match i {
i => {
let a = 1;
let b = 2;
},
_ => {},
}

match i {
i => {},
_ => {},
}

match i {
i => (),
_ => (),
}

match CONST_I32 {
CONST_I32 => println!(),
_ => {},
}
}
67 changes: 66 additions & 1 deletion tests/ui/single_match.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -216,5 +216,70 @@ LL | | None | Some(_) => {},
LL | | }
| |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }`

error: aborting due to 20 previous errors
error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match.rs:371:5
|
LL | / match DATA {
LL | | DATA => println!(),
LL | | _ => {},
LL | | }
| |_____^ help: try: `println!();`

error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match.rs:376:5
|
LL | / match CONST_I32 {
LL | | CONST_I32 => println!(),
LL | | _ => {},
LL | | }
| |_____^ help: try: `println!();`

error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match.rs:382:5
|
LL | / match i {
LL | | i => {
LL | | let a = 1;
LL | | let b = 2;
LL | | },
LL | | _ => {},
LL | | }
| |_____^
|
help: try
|
LL ~ {
LL + let a = 1;
LL + let b = 2;
LL + }
|

error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match.rs:390:5
|
LL | / match i {
LL | | i => {},
LL | | _ => {},
LL | | }
| |_____^ help: `match` expression can be removed

error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match.rs:395:5
|
LL | / match i {
LL | | i => (),
LL | | _ => (),
LL | | }
| |_____^ help: `match` expression can be removed

error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match.rs:400:5
|
LL | / match CONST_I32 {
LL | | CONST_I32 => println!(),
LL | | _ => {},
LL | | }
| |_____^ help: try: `println!()`

error: aborting due to 26 previous errors

4 changes: 4 additions & 0 deletions tests/ui/single_match_else.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,7 @@ fn issue_10808(bar: Option<i32>) {
},
}
}

fn irrefutable_match() -> Option<&'static ExprNode> {
Some(&NODE)
}
10 changes: 10 additions & 0 deletions tests/ui/single_match_else.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,13 @@ fn issue_10808(bar: Option<i32>) {
},
}
}

fn irrefutable_match() -> Option<&'static ExprNode> {
match ExprNode::Butterflies {
ExprNode::Butterflies => Some(&NODE),
_ => {
let x = 5;
None
},
}
}
14 changes: 13 additions & 1 deletion tests/ui/single_match_else.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,17 @@ LL + println!("None");
LL + }
|

error: aborting due to 9 previous errors
error: this pattern is irrefutable, `match` is useless
--> tests/ui/single_match_else.rs:204:5
|
LL | / match ExprNode::Butterflies {
LL | | ExprNode::Butterflies => Some(&NODE),
LL | | _ => {
LL | | let x = 5;
LL | | None
LL | | },
LL | | }
| |_____^ help: try: `Some(&NODE)`

error: aborting due to 10 previous errors

0 comments on commit bcf528b

Please sign in to comment.