Skip to content

Commit dc54301

Browse files
committed
Lint unused parentheses around method receiver
1 parent a60d12c commit dc54301

9 files changed

Lines changed: 114 additions & 10 deletions

File tree

compiler/rustc_lint/src/unused.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
623623
enum UnusedDelimsCtx {
624624
FunctionArg,
625625
MethodArg,
626+
MethodReceiver,
626627
AssignedValue,
627628
AssignedValueLetElse,
628629
IfCond,
@@ -645,6 +646,7 @@ impl From<UnusedDelimsCtx> for &'static str {
645646
match ctx {
646647
UnusedDelimsCtx::FunctionArg => "function argument",
647648
UnusedDelimsCtx::MethodArg => "method argument",
649+
UnusedDelimsCtx::MethodReceiver => "method receiver",
648650
UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
649651
"assigned value"
650652
}
@@ -710,6 +712,24 @@ trait UnusedDelimLint {
710712
}
711713
}
712714

715+
// For method receivers, parentheses are necessary for certain expression types
716+
// to avoid parsing ambiguities, e.g. `(1..10).sum()`, `(*ptr).method()`, etc.
717+
// Also keep parens around blocks for readability.
718+
if ctx == UnusedDelimsCtx::MethodReceiver {
719+
match inner.kind {
720+
ast::ExprKind::Range(..)
721+
| ast::ExprKind::Unary(..)
722+
| ast::ExprKind::Binary(..)
723+
| ast::ExprKind::Cast(..)
724+
| ast::ExprKind::Type(..)
725+
| ast::ExprKind::Assign(..)
726+
| ast::ExprKind::AssignOp(..)
727+
| ast::ExprKind::AddrOf(..)
728+
| ast::ExprKind::Block(..) => return true,
729+
_ => {}
730+
}
731+
}
732+
713733
// Check it's range in LetScrutineeExpr
714734
if let ast::ExprKind::Range(..) = inner.kind
715735
&& matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
@@ -976,13 +996,15 @@ trait UnusedDelimLint {
976996
}
977997
// either function/method call, or something this lint doesn't care about
978998
ref call_or_other => {
979-
let (args_to_check, ctx) = match *call_or_other {
980-
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
981-
MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
999+
let (args_to_check, ctx, receiver) = match *call_or_other {
1000+
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg, None),
1001+
MethodCall(ref call) => {
1002+
(&call.args[..], UnusedDelimsCtx::MethodArg, Some(&call.receiver))
1003+
}
9821004
Closure(ref closure)
9831005
if matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
9841006
{
985-
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
1007+
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody, None)
9861008
}
9871009
// actual catch-all arm
9881010
_ => {
@@ -999,6 +1021,17 @@ trait UnusedDelimLint {
9991021
for arg in args_to_check {
10001022
self.check_unused_delims_expr(cx, arg, ctx, false, None, None, false);
10011023
}
1024+
if let Some(recv) = receiver {
1025+
self.check_unused_delims_expr(
1026+
cx,
1027+
recv,
1028+
UnusedDelimsCtx::MethodReceiver,
1029+
false,
1030+
None,
1031+
None,
1032+
false,
1033+
);
1034+
}
10021035
return;
10031036
}
10041037
};

library/alloc/src/rc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3242,7 +3242,7 @@ impl<T, A: Allocator> Weak<T, A> {
32423242
}
32433243

32443244
pub(crate) fn is_dangling<T: ?Sized>(ptr: *const T) -> bool {
3245-
(ptr.cast::<()>()).addr() == usize::MAX
3245+
ptr.cast::<()>().addr() == usize::MAX
32463246
}
32473247

32483248
/// Helper type to allow accessing the reference counts without

library/alloc/src/slice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ impl<T> [T] {
534534
unsafe {
535535
ptr::copy_nonoverlapping::<T>(
536536
buf.as_ptr(),
537-
(buf.as_mut_ptr()).add(buf.len()),
537+
buf.as_mut_ptr().add(buf.len()),
538538
buf.len(),
539539
);
540540
// `buf` has capacity of `self.len() * n`.
@@ -555,7 +555,7 @@ impl<T> [T] {
555555
// This is non-overlapping since `2^expn > rem`.
556556
ptr::copy_nonoverlapping::<T>(
557557
buf.as_ptr(),
558-
(buf.as_mut_ptr()).add(buf.len()),
558+
buf.as_mut_ptr().add(buf.len()),
559559
rem_len,
560560
);
561561
// `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).

library/compiler-builtins/libm/src/math/cbrt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ pub fn cbrt_round(x: f64, round: Round) -> FpResult<f64> {
194194
let mut cvt4: u64 = y1.to_bits();
195195
cvt4 = (cvt4 + (164 << 15)) & 0xffffffffffff0000u64;
196196

197-
if ((f64::from_bits(cvt4) - y1) - dy).abs() < hf64!("0x1p-60") || (zz).abs() == 1.0 {
197+
if ((f64::from_bits(cvt4) - y1) - dy).abs() < hf64!("0x1p-60") || zz.abs() == 1.0 {
198198
cvt3 = (cvt3 + (1u64 << 15)) & 0xffffffffffff0000u64;
199199
}
200200
}

library/core/src/ptr/const_ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl<T: PointeeSized> *const T {
2727
@capture { ptr: *const u8 } -> bool:
2828
// This use of `const_raw_ptr_comparison` has been explicitly blessed by t-lang.
2929
if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] {
30-
match (ptr).guaranteed_eq(null_mut()) {
30+
match ptr.guaranteed_eq(null_mut()) {
3131
Some(res) => res,
3232
// To remain maximally conservative, we stop execution when we don't
3333
// know whether the pointer is null or not.

src/tools/test-float-parse/src/validate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl Constants {
7171
let neg_inf_cutoff = -&inf_cutoff;
7272

7373
let powers_of_two: BTreeMap<i32, _> =
74-
(POWERS_OF_TWO_RANGE).map(|n| (n, two.pow(n))).collect();
74+
POWERS_OF_TWO_RANGE.map(|n| (n, two.pow(n))).collect();
7575
let mut half_ulp = powers_of_two.clone();
7676
half_ulp.iter_mut().for_each(|(_k, v)| *v = &*v / two_int);
7777

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ run-rustfix
2+
3+
#![deny(unused_parens)]
4+
5+
struct Thing;
6+
impl Thing {
7+
fn method(self) {}
8+
}
9+
10+
fn main() {
11+
// Unnecessary parens - should warn
12+
let x = Thing;
13+
x.method(); //~ ERROR unnecessary parentheses around method receiver
14+
15+
// Necessary parens - should NOT warn
16+
let _ = (1..10).sum::<i32>(); // Range expression
17+
let _ = (1_i32 + 2).abs(); // Binary expression
18+
let _ = (-1_i32).abs(); // Unary expression
19+
let _ = (true as i32).abs(); // Cast expression
20+
let _ = (&42).clone(); // AddrOf expression
21+
let _ = (&mut 42).clone(); // AddrOf mut expression
22+
23+
// Block expressions - should NOT warn
24+
let _ = ({ 1_i32 }).abs(); // Block expression
25+
let _ = (unsafe { std::mem::zeroed::<i32>() }).abs(); // Unsafe block expression
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ run-rustfix
2+
3+
#![deny(unused_parens)]
4+
5+
struct Thing;
6+
impl Thing {
7+
fn method(self) {}
8+
}
9+
10+
fn main() {
11+
// Unnecessary parens - should warn
12+
let x = Thing;
13+
(x).method(); //~ ERROR unnecessary parentheses around method receiver
14+
15+
// Necessary parens - should NOT warn
16+
let _ = (1..10).sum::<i32>(); // Range expression
17+
let _ = (1_i32 + 2).abs(); // Binary expression
18+
let _ = (-1_i32).abs(); // Unary expression
19+
let _ = (true as i32).abs(); // Cast expression
20+
let _ = (&42).clone(); // AddrOf expression
21+
let _ = (&mut 42).clone(); // AddrOf mut expression
22+
23+
// Block expressions - should NOT warn
24+
let _ = ({ 1_i32 }).abs(); // Block expression
25+
let _ = (unsafe { std::mem::zeroed::<i32>() }).abs(); // Unsafe block expression
26+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error: unnecessary parentheses around method receiver
2+
--> $DIR/unused-parens-method-receiver-issue-151985.rs:13:5
3+
|
4+
LL | (x).method();
5+
| ^ ^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unused-parens-method-receiver-issue-151985.rs:3:9
9+
|
10+
LL | #![deny(unused_parens)]
11+
| ^^^^^^^^^^^^^
12+
help: remove these parentheses
13+
|
14+
LL - (x).method();
15+
LL + x.method();
16+
|
17+
18+
error: aborting due to 1 previous error
19+

0 commit comments

Comments
 (0)