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

+15-1
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

+1-1
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

+1-2
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

+1
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

+6-6
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

+1-1
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

+2-2
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

+2-2
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

+1-1
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

+2-2
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

tests/ui/inference/issue-113354.fixed

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@run-rustfix
2+
#![allow(unused_braces)]
23
fn main() {
34
let _ = || { while let Some(_) = Some(1) { } }; //~ ERROR mismatched types
45
}

tests/ui/inference/issue-113354.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@run-rustfix
2+
#![allow(unused_braces)]
23
fn main() {
34
let _ = || { while Some(_) = Some(1) { } }; //~ ERROR mismatched types
45
}

tests/ui/inference/issue-113354.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/issue-113354.rs:3:24
2+
--> $DIR/issue-113354.rs:4:24
33
|
44
LL | let _ = || { while Some(_) = Some(1) { } };
55
| ^^^^^^^^^^^^^^^^^ expected `bool`, found `()`

tests/ui/issues/issue-13665.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ fn foo<'r>() {
66
let _ = maybe_value_ref.map(|& ref v| v);
77
let _ = maybe_value_ref.map(|& ref v| -> &'r u8 {v});
88
let _ = maybe_value_ref.map(|& ref v: &'r u8| -> &'r u8 {v});
9-
let _ = maybe_value_ref.map(|& ref v: &'r u8| {v});
9+
let _ = maybe_value_ref.map(|& ref v: &'r u8| v);
1010
}
1111

1212
fn main() {

tests/ui/issues/issue-16774.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn main() {
3636
{
3737
let mut test = X(Box::new(5));
3838
{
39-
let mut change = || { *test = 10 };
39+
let mut change = || *test = 10;
4040
change();
4141
}
4242
assert_eq!(*test, 10);

tests/ui/issues/issue-18685.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Tr {
77
fn foo(&self);
88

99
fn bar(&self) {
10-
(|| { self.foo() })()
10+
(|| self.foo() )()
1111
}
1212
}
1313

tests/ui/issues/issue-21306.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ use std::sync::Arc;
44

55
fn main() {
66
let x = 5;
7-
let command = Arc::new(Box::new(|| { x*2 }));
7+
let command = Arc::new(Box::new(|| x*2));
88
assert_eq!(command(), 10);
99
}

tests/ui/issues/issue-28181.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
fn bar<F>(f: F) -> usize where F: Fn([usize; 1]) -> usize { f([2]) }
33

44
fn main() {
5-
bar(|u| { u[0] });
5+
bar(|u| u[0]);
66
}

tests/ui/issues/issue-34569.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
fn main() {
1212
match 0 {
13-
e if (|| { e == 0 })() => {},
13+
e if (|| e == 0)() => {},
1414
1 => {},
1515
_ => {}
1616
}

tests/ui/iterators/invalid-iterator-chain-fixable.fixed

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ run-rustfix
2+
#![allow(unused_braces)]
23
use std::collections::hash_set::Iter;
34
use std::collections::HashSet;
45

tests/ui/iterators/invalid-iterator-chain-fixable.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ run-rustfix
2+
#![allow(unused_braces)]
23
use std::collections::hash_set::Iter;
34
use std::collections::HashSet;
45

tests/ui/iterators/invalid-iterator-chain-fixable.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X`
2-
--> $DIR/invalid-iterator-chain-fixable.rs:7:7
2+
--> $DIR/invalid-iterator-chain-fixable.rs:8:7
33
|
44
LL | let i = i.map(|x| x.clone());
55
| ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone`
@@ -10,7 +10,7 @@ LL | i.collect()
1010
but trait `FromIterator<_>` is implemented for it
1111
= help: for that trait implementation, expected `X`, found `&X`
1212
note: the method call chain might not have had the expected associated types
13-
--> $DIR/invalid-iterator-chain-fixable.rs:5:26
13+
--> $DIR/invalid-iterator-chain-fixable.rs:6:26
1414
|
1515
LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
1616
| ^^^^^^^^^^^ `Iterator::Item` is `&X` here
@@ -24,7 +24,7 @@ LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> where X: Clone {
2424
| ++++++++++++++
2525

2626
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
27-
--> $DIR/invalid-iterator-chain-fixable.rs:17:33
27+
--> $DIR/invalid-iterator-chain-fixable.rs:18:33
2828
|
2929
LL | println!("{}", scores.sum::<i32>());
3030
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
@@ -36,7 +36,7 @@ LL | println!("{}", scores.sum::<i32>());
3636
`i32` implements `Sum<&i32>`
3737
`i32` implements `Sum`
3838
note: the method call chain might not have had the expected associated types
39-
--> $DIR/invalid-iterator-chain-fixable.rs:14:10
39+
--> $DIR/invalid-iterator-chain-fixable.rs:15:10
4040
|
4141
LL | let v = vec![(0, 0)];
4242
| ------------ this expression has type `Vec<({integer}, {integer})>`
@@ -57,7 +57,7 @@ LL + a + b
5757
|
5858

5959
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
60-
--> $DIR/invalid-iterator-chain-fixable.rs:25:20
60+
--> $DIR/invalid-iterator-chain-fixable.rs:26:20
6161
|
6262
LL | .sum::<i32>(),
6363
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
@@ -69,7 +69,7 @@ LL | .sum::<i32>(),
6969
`i32` implements `Sum<&i32>`
7070
`i32` implements `Sum`
7171
note: the method call chain might not have had the expected associated types
72-
--> $DIR/invalid-iterator-chain-fixable.rs:23:14
72+
--> $DIR/invalid-iterator-chain-fixable.rs:24:14
7373
|
7474
LL | vec![0, 1]
7575
| ---------- this expression has type `Vec<{integer}>`
@@ -90,7 +90,7 @@ LL + .map(|x| { x })
9090
|
9191

9292
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
93-
--> $DIR/invalid-iterator-chain-fixable.rs:27:60
93+
--> $DIR/invalid-iterator-chain-fixable.rs:28:60
9494
|
9595
LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
9696
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
@@ -102,7 +102,7 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
102102
`i32` implements `Sum<&i32>`
103103
`i32` implements `Sum`
104104
note: the method call chain might not have had the expected associated types
105-
--> $DIR/invalid-iterator-chain-fixable.rs:27:38
105+
--> $DIR/invalid-iterator-chain-fixable.rs:28:38
106106
|
107107
LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
108108
| ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
@@ -118,7 +118,7 @@ LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::<i32>());
118118
|
119119

120120
error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
121-
--> $DIR/invalid-iterator-chain-fixable.rs:36:25
121+
--> $DIR/invalid-iterator-chain-fixable.rs:37:25
122122
|
123123
LL | let g: Vec<i32> = f.collect();
124124
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
@@ -127,7 +127,7 @@ LL | let g: Vec<i32> = f.collect();
127127
but trait `FromIterator<i32>` is implemented for it
128128
= help: for that trait implementation, expected `i32`, found `()`
129129
note: the method call chain might not have had the expected associated types
130-
--> $DIR/invalid-iterator-chain-fixable.rs:32:15
130+
--> $DIR/invalid-iterator-chain-fixable.rs:33:15
131131
|
132132
LL | let a = vec![0];
133133
| ------- this expression has type `Vec<{integer}>`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ run-rustfix
2+
#![deny(unused_parens)]
3+
#![deny(unused_braces)]
4+
pub fn main() {
5+
let _closure = |x: i32, y: i32| x * (x + (y * 2)); //~ ERROR unnecessary braces around closure body
6+
let _ = || 0 == 0; //~ ERROR unnecessary parentheses around closure body
7+
let _ = (0..).find(|n| n % 2 == 0); //~ ERROR unnecessary parentheses around closure body
8+
let _ = (0..).find(|n| n % 2 == 0); //~ ERROR unnecessary braces around closure body
9+
let _ = || {
10+
_ = 0;
11+
0 == 0 //~ ERROR unnecessary parentheses around block return value
12+
};
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ run-rustfix
2+
#![deny(unused_parens)]
3+
#![deny(unused_braces)]
4+
pub fn main() {
5+
let _closure = |x: i32, y: i32| { x * (x + (y * 2)) }; //~ ERROR unnecessary braces around closure body
6+
let _ = || (0 == 0); //~ ERROR unnecessary parentheses around closure body
7+
let _ = (0..).find(|n| (n % 2 == 0)); //~ ERROR unnecessary parentheses around closure body
8+
let _ = (0..).find(|n| {n % 2 == 0}); //~ ERROR unnecessary braces around closure body
9+
let _ = || {
10+
_ = 0;
11+
(0 == 0) //~ ERROR unnecessary parentheses around block return value
12+
};
13+
}

0 commit comments

Comments
 (0)