Skip to content

Add checking for unnecessary delims in closure body #136906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3511,7 +3511,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.
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::iter;

use rustc_ast as ast;
use rustc_ast::util::{classify, parser};
use rustc_ast::{ExprKind, StmtKind};
use rustc_ast::{ExprKind, FnRetTy, StmtKind};
use rustc_errors::{MultiSpan, pluralize};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
Expand Down Expand Up @@ -593,6 +593,7 @@ enum UnusedDelimsCtx {
AnonConst,
MatchArmExpr,
IndexExpr,
ClosureBody,
}

impl From<UnusedDelimsCtx> for &'static str {
Expand All @@ -614,6 +615,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",
}
}
}
Expand Down Expand Up @@ -909,6 +911,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;
Expand Down Expand Up @@ -1392,6 +1399,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()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2214,7 +2214,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,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,7 @@ impl<'ast, 'ra: 'ast, '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)
};

Expand Down
2 changes: 1 addition & 1 deletion library/core/src/unicode/unicode_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
2 changes: 1 addition & 1 deletion src/etc/test-float-parse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,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()
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/unused_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,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(
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_utils/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,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,
Expand All @@ -956,7 +956,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
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,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 {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/unicode-table-generator/src/range_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
1 change: 0 additions & 1 deletion tests/ui/async-await/issues/issue-54752-async-block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
//@ pp-exact

fn main() { let _a = (async { }); }
//~^ WARNING unnecessary parentheses around assigned value
15 changes: 0 additions & 15 deletions tests/ui/async-await/issues/issue-54752-async-block.stderr

This file was deleted.

36 changes: 36 additions & 0 deletions tests/ui/lint/unused/closure-body-issue-136741.fixed
Original file line number Diff line number Diff line change
@@ -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()
})
}
38 changes: 38 additions & 0 deletions tests/ui/lint/unused/closure-body-issue-136741.rs
Original file line number Diff line number Diff line change
@@ -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()
})
}
62 changes: 62 additions & 0 deletions tests/ui/lint/unused/closure-body-issue-136741.stderr
Original file line number Diff line number Diff line change
@@ -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

Loading