mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-26 14:40:32 +00:00
Auto merge of #11242 - samueltardieu:issue-11238, r=Centri3,giraffate
New lint `ignored_unit_patterns` This idea comes from #11238. I've put the lint in `pedantic` as it might trigger numerous positives (three in Clippy itself). changelog: [`ignored_unit_patterns`]: new lint
This commit is contained in:
commit
1eb254ef83
10 changed files with 121 additions and 3 deletions
|
@ -4890,6 +4890,7 @@ Released 2018-09-13
|
||||||
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
|
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
|
||||||
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
|
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
|
||||||
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
|
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
|
||||||
|
[`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns
|
||||||
[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
|
[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
|
||||||
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
|
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
|
||||||
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
|
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
|
||||||
|
|
|
@ -41,7 +41,7 @@ fn main() {
|
||||||
matches.get_one::<String>("type").map(String::as_str),
|
matches.get_one::<String>("type").map(String::as_str),
|
||||||
matches.get_flag("msrv"),
|
matches.get_flag("msrv"),
|
||||||
) {
|
) {
|
||||||
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
|
Ok(()) => update_lints::update(update_lints::UpdateMode::Change),
|
||||||
Err(e) => eprintln!("Unable to create lint: {e}"),
|
Err(e) => eprintln!("Unable to create lint: {e}"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,7 +47,7 @@ fn check_install_precondition(force_override: bool) -> bool {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match fs::create_dir(vs_dir_path) {
|
match fs::create_dir(vs_dir_path) {
|
||||||
Ok(_) => {
|
Ok(()) => {
|
||||||
println!("info: created `{VSCODE_DIR}` directory for clippy");
|
println!("info: created `{VSCODE_DIR}` directory for clippy");
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
@ -203,6 +203,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||||
crate::if_let_mutex::IF_LET_MUTEX_INFO,
|
crate::if_let_mutex::IF_LET_MUTEX_INFO,
|
||||||
crate::if_not_else::IF_NOT_ELSE_INFO,
|
crate::if_not_else::IF_NOT_ELSE_INFO,
|
||||||
crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
|
crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
|
||||||
|
crate::ignored_unit_patterns::IGNORED_UNIT_PATTERNS_INFO,
|
||||||
crate::implicit_hasher::IMPLICIT_HASHER_INFO,
|
crate::implicit_hasher::IMPLICIT_HASHER_INFO,
|
||||||
crate::implicit_return::IMPLICIT_RETURN_INFO,
|
crate::implicit_return::IMPLICIT_RETURN_INFO,
|
||||||
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
|
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
|
||||||
|
|
52
clippy_lints/src/ignored_unit_patterns.rs
Normal file
52
clippy_lints/src/ignored_unit_patterns.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
|
use hir::PatKind;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir as hir;
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks for usage of `_` in patterns of type `()`.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Matching with `()` explicitly instead of `_` outlines
|
||||||
|
/// the fact that the pattern contains no data. Also it
|
||||||
|
/// would detect a type change that `_` would ignore.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// match std::fs::create_dir("tmp-work-dir") {
|
||||||
|
/// Ok(_) => println!("Working directory created"),
|
||||||
|
/// Err(s) => eprintln!("Could not create directory: {s}"),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// match std::fs::create_dir("tmp-work-dir") {
|
||||||
|
/// Ok(()) => println!("Working directory created"),
|
||||||
|
/// Err(s) => eprintln!("Could not create directory: {s}"),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.73.0"]
|
||||||
|
pub IGNORED_UNIT_PATTERNS,
|
||||||
|
pedantic,
|
||||||
|
"suggest replacing `_` by `()` in patterns where appropriate"
|
||||||
|
}
|
||||||
|
declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
|
||||||
|
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
|
||||||
|
if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).is_unit() {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
IGNORED_UNIT_PATTERNS,
|
||||||
|
pat.span,
|
||||||
|
"matching over `()` is more explicit",
|
||||||
|
"use `()` instead of `_`",
|
||||||
|
String::from("()"),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -147,6 +147,7 @@ mod future_not_send;
|
||||||
mod if_let_mutex;
|
mod if_let_mutex;
|
||||||
mod if_not_else;
|
mod if_not_else;
|
||||||
mod if_then_some_else_none;
|
mod if_then_some_else_none;
|
||||||
|
mod ignored_unit_patterns;
|
||||||
mod implicit_hasher;
|
mod implicit_hasher;
|
||||||
mod implicit_return;
|
mod implicit_return;
|
||||||
mod implicit_saturating_add;
|
mod implicit_saturating_add;
|
||||||
|
@ -1093,6 +1094,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
|
store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
|
||||||
|
store.register_late_pass(|_| Box::new(ignored_unit_patterns::IgnoredUnitPatterns));
|
||||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ fn try_get_option_occurrence<'tcx>(
|
||||||
});
|
});
|
||||||
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
|
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
|
||||||
match some_captures.get(local_id)
|
match some_captures.get(local_id)
|
||||||
.or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|_| none_captures.get(local_id)))
|
.or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|()| none_captures.get(local_id)))
|
||||||
{
|
{
|
||||||
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
|
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
|
||||||
Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
|
Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
|
||||||
|
|
17
tests/ui/ignored_unit_patterns.fixed
Normal file
17
tests/ui/ignored_unit_patterns.fixed
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//@run-rustfix
|
||||||
|
|
||||||
|
#![warn(clippy::ignored_unit_patterns)]
|
||||||
|
#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
|
||||||
|
|
||||||
|
fn foo() -> Result<(), ()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match foo() {
|
||||||
|
Ok(()) => {},
|
||||||
|
Err(()) => {},
|
||||||
|
}
|
||||||
|
if let Ok(()) = foo() {}
|
||||||
|
let _ = foo().map_err(|()| todo!());
|
||||||
|
}
|
17
tests/ui/ignored_unit_patterns.rs
Normal file
17
tests/ui/ignored_unit_patterns.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//@run-rustfix
|
||||||
|
|
||||||
|
#![warn(clippy::ignored_unit_patterns)]
|
||||||
|
#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
|
||||||
|
|
||||||
|
fn foo() -> Result<(), ()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match foo() {
|
||||||
|
Ok(_) => {},
|
||||||
|
Err(_) => {},
|
||||||
|
}
|
||||||
|
if let Ok(_) = foo() {}
|
||||||
|
let _ = foo().map_err(|_| todo!());
|
||||||
|
}
|
28
tests/ui/ignored_unit_patterns.stderr
Normal file
28
tests/ui/ignored_unit_patterns.stderr
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
error: matching over `()` is more explicit
|
||||||
|
--> $DIR/ignored_unit_patterns.rs:12:12
|
||||||
|
|
|
||||||
|
LL | Ok(_) => {},
|
||||||
|
| ^ help: use `()` instead of `_`: `()`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::ignored-unit-patterns` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: matching over `()` is more explicit
|
||||||
|
--> $DIR/ignored_unit_patterns.rs:13:13
|
||||||
|
|
|
||||||
|
LL | Err(_) => {},
|
||||||
|
| ^ help: use `()` instead of `_`: `()`
|
||||||
|
|
||||||
|
error: matching over `()` is more explicit
|
||||||
|
--> $DIR/ignored_unit_patterns.rs:15:15
|
||||||
|
|
|
||||||
|
LL | if let Ok(_) = foo() {}
|
||||||
|
| ^ help: use `()` instead of `_`: `()`
|
||||||
|
|
||||||
|
error: matching over `()` is more explicit
|
||||||
|
--> $DIR/ignored_unit_patterns.rs:16:28
|
||||||
|
|
|
||||||
|
LL | let _ = foo().map_err(|_| todo!());
|
||||||
|
| ^ help: use `()` instead of `_`: `()`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
Loading…
Reference in a new issue