Skip to content

Commit ccdf053

Browse files
committed
Add checking for unnecessary delims in closure body
1 parent 34a5ea9 commit ccdf053

35 files changed

+163
-45
lines changed

compiler/rustc_lint/src/unused.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
33

44
use rustc_ast as ast;
55
use rustc_ast::util::{classify, parser};
6-
use rustc_ast::{ExprKind, StmtKind};
6+
use rustc_ast::{ExprKind, FnRetTy, StmtKind};
77
use rustc_errors::{MultiSpan, pluralize};
88
use rustc_hir::def::{DefKind, Res};
99
use rustc_hir::def_id::DefId;
@@ -594,6 +594,7 @@ enum UnusedDelimsCtx {
594594
AnonConst,
595595
MatchArmExpr,
596596
IndexExpr,
597+
ClosureBody,
597598
}
598599

599600
impl From<UnusedDelimsCtx> for &'static str {
@@ -615,6 +616,7 @@ impl From<UnusedDelimsCtx> for &'static str {
615616
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
616617
UnusedDelimsCtx::MatchArmExpr => "match arm expression",
617618
UnusedDelimsCtx::IndexExpr => "index expression",
619+
UnusedDelimsCtx::ClosureBody => "closure body",
618620
}
619621
}
620622
}
@@ -933,6 +935,18 @@ trait UnusedDelimLint {
933935
let (args_to_check, ctx) = match *call_or_other {
934936
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
935937
MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
938+
Closure(ref closure)
939+
if matches!(closure.fn_decl.output, FnRetTy::Default(_))
940+
// skip `#[core::contracts::requires(...)]` and `#[core::contracts::ensures(...)]` which generate closure
941+
&& !cx
942+
.sess()
943+
.source_map()
944+
.span_to_snippet(closure.fn_decl_span)
945+
.unwrap_or_default()
946+
.contains("core::contracts") =>
947+
{
948+
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
949+
}
936950
// actual catch-all arm
937951
_ => {
938952
return;

tests/ui/closures/issue-10682.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ fn foo<F:FnOnce()>(_: F) {}
88

99
pub fn main() {
1010
let a = Box::new(1);
11-
foo(move|| { foo(move|| { work(a) }) })
11+
foo(move|| foo(move|| work(a) ) )
1212
}

tests/ui/closures/issue-5239-2.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
//@ run-pass
22
// Regression test for issue #5239
33

4-
54
pub fn main() {
6-
let _f = |ref x: isize| { *x };
5+
let _f = |ref x: isize| *x;
76
let foo = 10;
87
assert_eq!(_f(foo), 10);
98
}

tests/ui/closures/issue-868.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ run-pass
22
#![allow(unused_parens)]
3+
#![allow(unused_braces)]
34
#![allow(unit_bindings)]
45

56
fn f<T, F>(g: F) -> T where F: FnOnce() -> T { g() }

tests/ui/coercion/coerce-expect-unsized.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ pub fn main() {
1212
let _: Box<[isize]> = Box::new({ [1, 2, 3] });
1313
let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] });
1414
let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] });
15-
let _: Box<dyn Fn(isize) -> _> = Box::new({ |x| (x as u8) });
15+
let _: Box<dyn Fn(isize) -> _> = Box::new({ |x| x as u8 });
1616
let _: Box<dyn Debug> = Box::new(if true { false } else { true });
1717
let _: Box<dyn Debug> = Box::new(match true { true => 'a', false => 'b' });
1818

1919
let _: &[isize] = &{ [1, 2, 3] };
2020
let _: &[isize] = &if true { [1, 2, 3] } else { [1, 3, 4] };
2121
let _: &[isize] = &match true { true => [1, 2, 3], false => [1, 3, 4] };
22-
let _: &dyn Fn(isize) -> _ = &{ |x| (x as u8) };
22+
let _: &dyn Fn(isize) -> _ = &{ |x| x as u8 };
2323
let _: &dyn Debug = &if true { false } else { true };
2424
let _: &dyn Debug = &match true { true => 'a', false => 'b' };
2525

@@ -31,13 +31,13 @@ pub fn main() {
3131
};
3232

3333
let _: Box<[isize]> = Box::new([1, 2, 3]);
34-
let _: Box<dyn Fn(isize) -> _> = Box::new(|x| (x as u8));
34+
let _: Box<dyn Fn(isize) -> _> = Box::new(|x| x as u8);
3535

3636
let _: Rc<RefCell<[isize]>> = Rc::new(RefCell::new([1, 2, 3]));
37-
let _: Rc<RefCell<dyn FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| (x as u8)));
37+
let _: Rc<RefCell<dyn FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| x as u8));
3838

3939
let _: Vec<Box<dyn Fn(isize) -> _>> = vec![
40-
Box::new(|x| (x as u8)),
41-
Box::new(|x| (x as i16 as u8)),
40+
Box::new(|x| x as u8),
41+
Box::new(|x| x as i16 as u8),
4242
];
4343
}

tests/ui/consts/issue-27890.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@ run-pass
2-
static PLUS_ONE: &'static (dyn Fn(i32) -> i32 + Sync) = (&|x: i32| { x + 1 })
2+
static PLUS_ONE: &'static (dyn Fn(i32) -> i32 + Sync) = (&|x: i32| x + 1)
33
as &'static (dyn Fn(i32) -> i32 + Sync);
44

55
fn main() {

tests/ui/coroutine/smoke.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn send_and_sync() {
150150

151151
#[test]
152152
fn send_over_threads() {
153-
let mut foo = #[coroutine] || { yield };
153+
let mut foo = #[coroutine] || yield;
154154
thread::spawn(move || {
155155
match Pin::new(&mut foo).resume(()) {
156156
CoroutineState::Yielded(()) => {}
@@ -163,7 +163,7 @@ fn send_over_threads() {
163163
}).join().unwrap();
164164

165165
let a = String::from("a");
166-
let mut foo = #[coroutine] || { yield a };
166+
let mut foo = #[coroutine] || yield a;
167167
thread::spawn(move || {
168168
match Pin::new(&mut foo).resume(()) {
169169
CoroutineState::Yielded(ref s) if *s == "a" => {}

tests/ui/functions-closures/closure-to-fn-coercion.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@ run-pass
22
use std::mem;
33

4-
const FOO: fn(u8) -> u8 = |v: u8| { v };
4+
const FOO: fn(u8) -> u8 = |v: u8| v;
55

66
const BAR: [fn(&mut u32); 5] = [
77
|_: &mut u32| {},
@@ -21,7 +21,7 @@ fn generic<T>(_: T) -> fn() -> usize {
2121
fn main() {
2222
// Items
2323
assert_eq!(func_specific()(), 42);
24-
let foo: fn(u8) -> u8 = |v: u8| { v };
24+
let foo: fn(u8) -> u8 = |v: u8| v;
2525
assert_eq!(foo(31), 31);
2626
// Constants
2727
assert_eq!(FOO(31), 31);

tests/ui/impl-trait/closure-in-impl-trait-arg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ run-pass
22
#![allow(unused_must_use)]
3-
fn bug(_: impl Iterator<Item = [(); { |x: u32| { x }; 4 }]>) {}
3+
fn bug(_: impl Iterator<Item = [(); { |x: u32| x ; 4 }]>) {}
44

55
fn main() {
66
bug(std::iter::empty());

tests/ui/impl-trait/closure-in-impl-trait.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//@ run-pass
22
#![allow(unused_must_use)]
3-
fn bug<T>() -> impl Iterator<Item = [(); { |x: u32| { x }; 4 }]> {
3+
fn bug<T>() -> impl Iterator<Item = [(); { |x: u32| x; 4 }]> {
44
std::iter::empty()
55
}
66

7-
fn ok<T>() -> Box<dyn Iterator<Item = [(); { |x: u32| { x }; 4 }]>> {
7+
fn ok<T>() -> Box<dyn Iterator<Item = [(); { |x: u32| x; 4 }]>> {
88
Box::new(std::iter::empty())
99
}
1010

0 commit comments

Comments
 (0)