Remove uncessary parens in closure body with unused lint

This commit is contained in:
yukang 2025-06-29 11:40:59 +08:00
parent e43d139a82
commit 93db9e7ee0
15 changed files with 160 additions and 27 deletions

View file

@ -3526,7 +3526,7 @@ pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
// All the chars that differ in capitalization are confusable (above):
let confusable = iter::zip(found.chars(), suggested.chars())
.filter(|(f, s)| f != s)
.all(|(f, s)| (ascii_confusables.contains(&f) || ascii_confusables.contains(&s)));
.all(|(f, s)| ascii_confusables.contains(&f) || ascii_confusables.contains(&s));
confusable && found.to_lowercase() == suggested.to_lowercase()
// FIXME: We sometimes suggest the same thing we already have, which is a
// bug, but be defensive against that here.

View file

@ -1,7 +1,7 @@
use std::iter;
use rustc_ast::util::{classify, parser};
use rustc_ast::{self as ast, ExprKind, HasAttrs as _, StmtKind};
use rustc_ast::{self as ast, ExprKind, FnRetTy, HasAttrs as _, StmtKind};
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{MultiSpan, pluralize};
@ -599,6 +599,7 @@ enum UnusedDelimsCtx {
AnonConst,
MatchArmExpr,
IndexExpr,
ClosureBody,
}
impl From<UnusedDelimsCtx> for &'static str {
@ -620,6 +621,7 @@ impl From<UnusedDelimsCtx> for &'static str {
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
UnusedDelimsCtx::MatchArmExpr => "match arm expression",
UnusedDelimsCtx::IndexExpr => "index expression",
UnusedDelimsCtx::ClosureBody => "closure body",
}
}
}
@ -919,6 +921,11 @@ trait UnusedDelimLint {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
Closure(ref closure)
if matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
{
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
}
// actual catch-all arm
_ => {
return;
@ -1508,6 +1515,7 @@ impl UnusedDelimLint for UnusedBraces {
&& (ctx != UnusedDelimsCtx::AnonConst
|| (matches!(expr.kind, ast::ExprKind::Lit(_))
&& !expr.span.from_expansion()))
&& ctx != UnusedDelimsCtx::ClosureBody
&& !cx.sess().source_map().is_multiline(value.span)
&& value.attrs.is_empty()
&& !value.span.from_expansion()

View file

@ -2206,7 +2206,7 @@ impl<'a> Parser<'a> {
if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
return IsMacroRulesItem::Yes { has_bang: true };
} else if self.look_ahead(1, |t| (t.is_ident())) {
} else if self.look_ahead(1, |t| t.is_ident()) {
// macro_rules foo
self.dcx().emit_err(errors::MacroRulesMissingBang {
span: macro_rules_span,

View file

@ -328,8 +328,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let module_did = mod_prefix.as_ref().and_then(Res::mod_def_id);
let mod_prefix =
mod_prefix.map_or_else(String::new, |res| (format!("{} ", res.descr())));
mod_prefix.map_or_else(String::new, |res| format!("{} ", res.descr()));
(mod_prefix, format!("`{}`", Segment::names_to_string(mod_path)), module_did, None)
};

View file

@ -82,7 +82,7 @@ unsafe fn skip_search<const SOR: usize, const OFFSETS: usize>(
let needle = needle as u32;
let last_idx =
match short_offset_runs.binary_search_by_key(&(needle << 11), |header| (header.0 << 11)) {
match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header.0 << 11) {
Ok(idx) => idx + 1,
Err(idx) => idx,
};

View file

@ -169,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
let iter = self
.unused_async_fns
.iter()
.filter(|UnusedAsyncFn { def_id, .. }| (!self.async_fns_as_value.contains(def_id)));
.filter(|UnusedAsyncFn { def_id, .. }| !self.async_fns_as_value.contains(def_id));
for fun in iter {
span_lint_hir_and_then(

View file

@ -889,7 +889,7 @@ impl AdtVariantInfo {
.enumerate()
.map(|(i, f)| (i, approx_ty_size(cx, f.ty(cx.tcx, subst))))
.collect::<Vec<_>>();
fields_size.sort_by(|(_, a_size), (_, b_size)| (a_size.cmp(b_size)));
fields_size.sort_by(|(_, a_size), (_, b_size)| a_size.cmp(b_size));
Self {
ind: i,
@ -898,7 +898,7 @@ impl AdtVariantInfo {
}
})
.collect::<Vec<_>>();
variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));
variants_size.sort_by(|a, b| b.size.cmp(&a.size));
variants_size
}
}

View file

@ -1777,6 +1777,12 @@ impl<'test> TestCx<'test> {
// Allow tests to use internal features.
rustc.args(&["-A", "internal_features"]);
// Allow tests to have unused parens and braces.
// Add #![deny(unused_parens, unused_braces)] to the test file if you want to
// test that these lints are working.
rustc.args(&["-A", "unused_parens"]);
rustc.args(&["-A", "unused_braces"]);
if self.props.force_host {
self.maybe_add_external_args(&mut rustc, &self.config.host_rustcflags);
if !is_rustdoc {

View file

@ -340,7 +340,7 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration {
for test in tests.iter_mut() {
test.progress = Some(ui::Progress::new(test, &mut all_progress_bars));
ui::set_panic_hook(&all_progress_bars);
((test.launch)(test, cfg));
(test.launch)(test, cfg);
}
start.elapsed()

View file

@ -80,7 +80,7 @@ unsafe fn skip_search<const SOR: usize, const OFFSETS: usize>(
let needle = needle as u32;
let last_idx =
match short_offset_runs.binary_search_by_key(&(needle << 11), |header| (header.0 << 11)) {
match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header.0 << 11) {
Ok(idx) => idx + 1,
Err(idx) => idx,
};

View file

@ -4,4 +4,3 @@
//@ pp-exact
fn main() { let _a = (async { }); }
//~^ WARNING unnecessary parentheses around assigned value

View file

@ -1,15 +0,0 @@
warning: unnecessary parentheses around assigned value
--> $DIR/issue-54752-async-block.rs:6:22
|
LL | fn main() { let _a = (async { }); }
| ^ ^
|
= note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
|
LL - fn main() { let _a = (async { }); }
LL + fn main() { let _a = async { }; }
|
warning: 1 warning emitted

View file

@ -0,0 +1,36 @@
//@ run-rustfix
// ignore-tidy-linelength
#![deny(unused_parens)]
#![deny(unused_braces)]
fn long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces()
{}
fn func(f: impl FnOnce()) {
f()
}
pub fn main() {
let _closure = |x: i32, y: i32| { x * (x + (y * 2)) };
let _ = || 0 == 0; //~ ERROR unnecessary parentheses around closure body
let _ = (0..).find(|n| n % 2 == 0); //~ ERROR unnecessary parentheses around closure body
let _ = (0..).find(|n| {n % 2 == 0});
// multiple lines of code will not lint with braces
let _ = (0..).find(|n| {
n % 2 == 0
});
// multiple lines of code will lint with parentheses
let _ = (0..).find(|n| n % 2 == 0);
let _ = || {
_ = 0;
0 == 0 //~ ERROR unnecessary parentheses around block return value
};
// long expressions will not lint with braces
func(|| {
long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces()
})
}

View file

@ -0,0 +1,38 @@
//@ run-rustfix
// ignore-tidy-linelength
#![deny(unused_parens)]
#![deny(unused_braces)]
fn long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces()
{}
fn func(f: impl FnOnce()) {
f()
}
pub fn main() {
let _closure = |x: i32, y: i32| { x * (x + (y * 2)) };
let _ = || (0 == 0); //~ ERROR unnecessary parentheses around closure body
let _ = (0..).find(|n| (n % 2 == 0)); //~ ERROR unnecessary parentheses around closure body
let _ = (0..).find(|n| {n % 2 == 0});
// multiple lines of code will not lint with braces
let _ = (0..).find(|n| {
n % 2 == 0
});
// multiple lines of code will lint with parentheses
let _ = (0..).find(|n| ( //~ ERROR unnecessary parentheses around closure body
n % 2 == 0
));
let _ = || {
_ = 0;
(0 == 0) //~ ERROR unnecessary parentheses around block return value
};
// long expressions will not lint with braces
func(|| {
long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces_long_expr_that_does_not_require_braces()
})
}

View file

@ -0,0 +1,62 @@
error: unnecessary parentheses around closure body
--> $DIR/closure-body-issue-136741.rs:15:16
|
LL | let _ = || (0 == 0);
| ^ ^
|
note: the lint level is defined here
--> $DIR/closure-body-issue-136741.rs:3:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
help: remove these parentheses
|
LL - let _ = || (0 == 0);
LL + let _ = || 0 == 0;
|
error: unnecessary parentheses around closure body
--> $DIR/closure-body-issue-136741.rs:16:28
|
LL | let _ = (0..).find(|n| (n % 2 == 0));
| ^ ^
|
help: remove these parentheses
|
LL - let _ = (0..).find(|n| (n % 2 == 0));
LL + let _ = (0..).find(|n| n % 2 == 0);
|
error: unnecessary parentheses around closure body
--> $DIR/closure-body-issue-136741.rs:25:28
|
LL | let _ = (0..).find(|n| (
| _____________________________^
LL | | n % 2 == 0
| | ________^__________^
| ||________|
| |
LL | | ));
| |_____^
|
help: remove these parentheses
|
LL - let _ = (0..).find(|n| (
LL - n % 2 == 0
LL + let _ = (0..).find(|n| n % 2 == 0);
|
error: unnecessary parentheses around block return value
--> $DIR/closure-body-issue-136741.rs:31:9
|
LL | (0 == 0)
| ^ ^
|
help: remove these parentheses
|
LL - (0 == 0)
LL + 0 == 0
|
error: aborting due to 4 previous errors