Skip to content

Commit 1eb254e

Browse files
committed
Auto merge of rust-lang#11242 - samueltardieu:issue-11238, r=Centri3,giraffate
New lint `ignored_unit_patterns` This idea comes from rust-lang#11238. I've put the lint in `pedantic` as it might trigger numerous positives (three in Clippy itself). changelog: [`ignored_unit_patterns`]: new lint
2 parents 237dd59 + f9a6dfa commit 1eb254e

10 files changed

+121
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4890,6 +4890,7 @@ Released 2018-09-13
48904890
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
48914891
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
48924892
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
4893+
[`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns
48934894
[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
48944895
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
48954896
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher

clippy_dev/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn main() {
4141
matches.get_one::<String>("type").map(String::as_str),
4242
matches.get_flag("msrv"),
4343
) {
44-
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
44+
Ok(()) => update_lints::update(update_lints::UpdateMode::Change),
4545
Err(e) => eprintln!("Unable to create lint: {e}"),
4646
}
4747
},

clippy_dev/src/setup/vscode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn check_install_precondition(force_override: bool) -> bool {
4747
}
4848
} else {
4949
match fs::create_dir(vs_dir_path) {
50-
Ok(_) => {
50+
Ok(()) => {
5151
println!("info: created `{VSCODE_DIR}` directory for clippy");
5252
},
5353
Err(err) => {

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
203203
crate::if_let_mutex::IF_LET_MUTEX_INFO,
204204
crate::if_not_else::IF_NOT_ELSE_INFO,
205205
crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
206+
crate::ignored_unit_patterns::IGNORED_UNIT_PATTERNS_INFO,
206207
crate::implicit_hasher::IMPLICIT_HASHER_INFO,
207208
crate::implicit_return::IMPLICIT_RETURN_INFO,
208209
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use hir::PatKind;
3+
use rustc_errors::Applicability;
4+
use rustc_hir as hir;
5+
use rustc_lint::{LateContext, LateLintPass};
6+
use rustc_session::{declare_lint_pass, declare_tool_lint};
7+
8+
declare_clippy_lint! {
9+
/// ### What it does
10+
/// Checks for usage of `_` in patterns of type `()`.
11+
///
12+
/// ### Why is this bad?
13+
/// Matching with `()` explicitly instead of `_` outlines
14+
/// the fact that the pattern contains no data. Also it
15+
/// would detect a type change that `_` would ignore.
16+
///
17+
/// ### Example
18+
/// ```rust
19+
/// match std::fs::create_dir("tmp-work-dir") {
20+
/// Ok(_) => println!("Working directory created"),
21+
/// Err(s) => eprintln!("Could not create directory: {s}"),
22+
/// }
23+
/// ```
24+
/// Use instead:
25+
/// ```rust
26+
/// match std::fs::create_dir("tmp-work-dir") {
27+
/// Ok(()) => println!("Working directory created"),
28+
/// Err(s) => eprintln!("Could not create directory: {s}"),
29+
/// }
30+
/// ```
31+
#[clippy::version = "1.73.0"]
32+
pub IGNORED_UNIT_PATTERNS,
33+
pedantic,
34+
"suggest replacing `_` by `()` in patterns where appropriate"
35+
}
36+
declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]);
37+
38+
impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
39+
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
40+
if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).is_unit() {
41+
span_lint_and_sugg(
42+
cx,
43+
IGNORED_UNIT_PATTERNS,
44+
pat.span,
45+
"matching over `()` is more explicit",
46+
"use `()` instead of `_`",
47+
String::from("()"),
48+
Applicability::MachineApplicable,
49+
);
50+
}
51+
}
52+
}

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ mod future_not_send;
147147
mod if_let_mutex;
148148
mod if_not_else;
149149
mod if_then_some_else_none;
150+
mod ignored_unit_patterns;
150151
mod implicit_hasher;
151152
mod implicit_return;
152153
mod implicit_saturating_add;
@@ -1093,6 +1094,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10931094
})
10941095
});
10951096
store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
1097+
store.register_late_pass(|_| Box::new(ignored_unit_patterns::IgnoredUnitPatterns));
10961098
// add lints here, do not remove this comment, it's used in `new_lint`
10971099
}
10981100

clippy_lints/src/option_if_let_else.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ fn try_get_option_occurrence<'tcx>(
155155
});
156156
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
157157
match some_captures.get(local_id)
158-
.or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|_| none_captures.get(local_id)))
158+
.or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|()| none_captures.get(local_id)))
159159
{
160160
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
161161
Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,

tests/ui/ignored_unit_patterns.fixed

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@run-rustfix
2+
3+
#![warn(clippy::ignored_unit_patterns)]
4+
#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
5+
6+
fn foo() -> Result<(), ()> {
7+
unimplemented!()
8+
}
9+
10+
fn main() {
11+
match foo() {
12+
Ok(()) => {},
13+
Err(()) => {},
14+
}
15+
if let Ok(()) = foo() {}
16+
let _ = foo().map_err(|()| todo!());
17+
}

tests/ui/ignored_unit_patterns.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@run-rustfix
2+
3+
#![warn(clippy::ignored_unit_patterns)]
4+
#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
5+
6+
fn foo() -> Result<(), ()> {
7+
unimplemented!()
8+
}
9+
10+
fn main() {
11+
match foo() {
12+
Ok(_) => {},
13+
Err(_) => {},
14+
}
15+
if let Ok(_) = foo() {}
16+
let _ = foo().map_err(|_| todo!());
17+
}

tests/ui/ignored_unit_patterns.stderr

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: matching over `()` is more explicit
2+
--> $DIR/ignored_unit_patterns.rs:12:12
3+
|
4+
LL | Ok(_) => {},
5+
| ^ help: use `()` instead of `_`: `()`
6+
|
7+
= note: `-D clippy::ignored-unit-patterns` implied by `-D warnings`
8+
9+
error: matching over `()` is more explicit
10+
--> $DIR/ignored_unit_patterns.rs:13:13
11+
|
12+
LL | Err(_) => {},
13+
| ^ help: use `()` instead of `_`: `()`
14+
15+
error: matching over `()` is more explicit
16+
--> $DIR/ignored_unit_patterns.rs:15:15
17+
|
18+
LL | if let Ok(_) = foo() {}
19+
| ^ help: use `()` instead of `_`: `()`
20+
21+
error: matching over `()` is more explicit
22+
--> $DIR/ignored_unit_patterns.rs:16:28
23+
|
24+
LL | let _ = foo().map_err(|_| todo!());
25+
| ^ help: use `()` instead of `_`: `()`
26+
27+
error: aborting due to 4 previous errors
28+

0 commit comments

Comments
 (0)