Skip to content

Commit bcf528b

Browse files
committed
Auto merge of rust-lang#13324 - WeiTheShinobi:single_match, r=dswij
[`single_match`, `single_match_else`] fix suggestion when match irrefutable fixes rust-lang#13012 changelog:[`single_match`, `single_match_else`]: fix suggestion when `match` irrefutable
2 parents 41dc86d + e3ca249 commit bcf528b

7 files changed

+184
-4
lines changed

clippy_lints/src/matches/single_match.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::source::{expr_block, snippet, SpanRangeExt};
2+
use clippy_utils::source::{expr_block, snippet, snippet_block_with_context, SpanRangeExt};
33
use clippy_utils::ty::implements_trait;
44
use clippy_utils::{
55
is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
@@ -9,7 +9,7 @@ use rustc_arena::DroplessArena;
99
use rustc_errors::Applicability;
1010
use rustc_hir::def::{DefKind, Res};
1111
use rustc_hir::intravisit::{walk_pat, Visitor};
12-
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind, QPath};
12+
use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
1313
use rustc_lint::LateContext;
1414
use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
1515
use rustc_span::{sym, Span};
@@ -91,6 +91,29 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
9191
format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
9292
});
9393

94+
if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
95+
let msg = "this pattern is irrefutable, `match` is useless";
96+
let (sugg, help) = if is_unit_expr(arm.body) {
97+
(String::new(), "`match` expression can be removed")
98+
} else {
99+
let mut sugg = snippet_block_with_context(cx, arm.body.span, ctxt, "..", Some(expr.span), &mut app)
100+
.0
101+
.to_string();
102+
if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
103+
&& let StmtKind::Expr(_) = stmt.kind
104+
&& match arm.body.kind {
105+
ExprKind::Block(block, _) => block.span.from_expansion(),
106+
_ => true,
107+
}
108+
{
109+
sugg.push(';');
110+
}
111+
(sugg, "try")
112+
};
113+
span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg.to_string(), app);
114+
return;
115+
}
116+
94117
let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
95118
let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
96119
&& let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))

tests/ui/single_match.fixed

+24
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,27 @@ fn issue11365() {
296296

297297
if let Some(A | B) = &Some(A) { println!() }
298298
}
299+
300+
#[derive(Eq, PartialEq)]
301+
pub struct Data([u8; 4]);
302+
303+
const DATA: Data = Data([1, 2, 3, 4]);
304+
const CONST_I32: i32 = 1;
305+
306+
fn irrefutable_match() {
307+
println!();
308+
309+
println!();
310+
311+
let i = 0;
312+
{
313+
let a = 1;
314+
let b = 2;
315+
}
316+
317+
318+
319+
320+
321+
println!()
322+
}

tests/ui/single_match.rs

+42
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,45 @@ fn issue11365() {
360360
None | Some(_) => {},
361361
}
362362
}
363+
364+
#[derive(Eq, PartialEq)]
365+
pub struct Data([u8; 4]);
366+
367+
const DATA: Data = Data([1, 2, 3, 4]);
368+
const CONST_I32: i32 = 1;
369+
370+
fn irrefutable_match() {
371+
match DATA {
372+
DATA => println!(),
373+
_ => {},
374+
}
375+
376+
match CONST_I32 {
377+
CONST_I32 => println!(),
378+
_ => {},
379+
}
380+
381+
let i = 0;
382+
match i {
383+
i => {
384+
let a = 1;
385+
let b = 2;
386+
},
387+
_ => {},
388+
}
389+
390+
match i {
391+
i => {},
392+
_ => {},
393+
}
394+
395+
match i {
396+
i => (),
397+
_ => (),
398+
}
399+
400+
match CONST_I32 {
401+
CONST_I32 => println!(),
402+
_ => {},
403+
}
404+
}

tests/ui/single_match.stderr

+66-1
Original file line numberDiff line numberDiff line change
@@ -216,5 +216,70 @@ LL | | None | Some(_) => {},
216216
LL | | }
217217
| |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }`
218218

219-
error: aborting due to 20 previous errors
219+
error: this pattern is irrefutable, `match` is useless
220+
--> tests/ui/single_match.rs:371:5
221+
|
222+
LL | / match DATA {
223+
LL | | DATA => println!(),
224+
LL | | _ => {},
225+
LL | | }
226+
| |_____^ help: try: `println!();`
227+
228+
error: this pattern is irrefutable, `match` is useless
229+
--> tests/ui/single_match.rs:376:5
230+
|
231+
LL | / match CONST_I32 {
232+
LL | | CONST_I32 => println!(),
233+
LL | | _ => {},
234+
LL | | }
235+
| |_____^ help: try: `println!();`
236+
237+
error: this pattern is irrefutable, `match` is useless
238+
--> tests/ui/single_match.rs:382:5
239+
|
240+
LL | / match i {
241+
LL | | i => {
242+
LL | | let a = 1;
243+
LL | | let b = 2;
244+
LL | | },
245+
LL | | _ => {},
246+
LL | | }
247+
| |_____^
248+
|
249+
help: try
250+
|
251+
LL ~ {
252+
LL + let a = 1;
253+
LL + let b = 2;
254+
LL + }
255+
|
256+
257+
error: this pattern is irrefutable, `match` is useless
258+
--> tests/ui/single_match.rs:390:5
259+
|
260+
LL | / match i {
261+
LL | | i => {},
262+
LL | | _ => {},
263+
LL | | }
264+
| |_____^ help: `match` expression can be removed
265+
266+
error: this pattern is irrefutable, `match` is useless
267+
--> tests/ui/single_match.rs:395:5
268+
|
269+
LL | / match i {
270+
LL | | i => (),
271+
LL | | _ => (),
272+
LL | | }
273+
| |_____^ help: `match` expression can be removed
274+
275+
error: this pattern is irrefutable, `match` is useless
276+
--> tests/ui/single_match.rs:400:5
277+
|
278+
LL | / match CONST_I32 {
279+
LL | | CONST_I32 => println!(),
280+
LL | | _ => {},
281+
LL | | }
282+
| |_____^ help: try: `println!()`
283+
284+
error: aborting due to 26 previous errors
220285

tests/ui/single_match_else.fixed

+4
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,7 @@ fn issue_10808(bar: Option<i32>) {
171171
},
172172
}
173173
}
174+
175+
fn irrefutable_match() -> Option<&'static ExprNode> {
176+
Some(&NODE)
177+
}

tests/ui/single_match_else.rs

+10
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,13 @@ fn issue_10808(bar: Option<i32>) {
199199
},
200200
}
201201
}
202+
203+
fn irrefutable_match() -> Option<&'static ExprNode> {
204+
match ExprNode::Butterflies {
205+
ExprNode::Butterflies => Some(&NODE),
206+
_ => {
207+
let x = 5;
208+
None
209+
},
210+
}
211+
}

tests/ui/single_match_else.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,17 @@ LL + println!("None");
197197
LL + }
198198
|
199199

200-
error: aborting due to 9 previous errors
200+
error: this pattern is irrefutable, `match` is useless
201+
--> tests/ui/single_match_else.rs:204:5
202+
|
203+
LL | / match ExprNode::Butterflies {
204+
LL | | ExprNode::Butterflies => Some(&NODE),
205+
LL | | _ => {
206+
LL | | let x = 5;
207+
LL | | None
208+
LL | | },
209+
LL | | }
210+
| |_____^ help: try: `Some(&NODE)`
211+
212+
error: aborting due to 10 previous errors
201213

0 commit comments

Comments
 (0)