Skip to content

Commit 885e44e

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

File tree

12 files changed

+120
-20
lines changed

12 files changed

+120
-20
lines changed

compiler/rustc_lint/src/unused.rs

Lines changed: 30 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,16 @@ trait UnusedDelimLint {
710712
}
711713
}
712714

715+
// For method receivers, only lint simple path expressions like `(x).method()`.
716+
// Keep parens for all other cases to avoid false positives with complex expressions
717+
// like `(1..10).sum()`, `(*ptr).method()`, `({ block }).method()`, etc.
718+
// Only lint simple variable names like `(x).method()`
719+
if ctx == UnusedDelimsCtx::MethodReceiver {
720+
if !matches!(inner.kind, ast::ExprKind::Path(None, _)) {
721+
return true;
722+
}
723+
}
724+
713725
// Check it's range in LetScrutineeExpr
714726
if let ast::ExprKind::Range(..) = inner.kind
715727
&& matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
@@ -976,13 +988,15 @@ trait UnusedDelimLint {
976988
}
977989
// either function/method call, or something this lint doesn't care about
978990
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),
991+
let (args_to_check, ctx, receiver) = match *call_or_other {
992+
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg, None),
993+
MethodCall(ref call) => {
994+
(&call.args[..], UnusedDelimsCtx::MethodArg, Some(&call.receiver))
995+
}
982996
Closure(ref closure)
983997
if matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
984998
{
985-
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
999+
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody, None)
9861000
}
9871001
// actual catch-all arm
9881002
_ => {
@@ -999,6 +1013,17 @@ trait UnusedDelimLint {
9991013
for arg in args_to_check {
10001014
self.check_unused_delims_expr(cx, arg, ctx, false, None, None, false);
10011015
}
1016+
if let Some(recv) = receiver {
1017+
self.check_unused_delims_expr(
1018+
cx,
1019+
recv,
1020+
UnusedDelimsCtx::MethodReceiver,
1021+
false,
1022+
None,
1023+
None,
1024+
false,
1025+
);
1026+
}
10021027
return;
10031028
}
10041029
};
@@ -1584,6 +1609,7 @@ impl UnusedDelimLint for UnusedBraces {
15841609
if let [stmt] = inner.stmts.as_slice()
15851610
&& let ast::StmtKind::Expr(ref expr) = stmt.kind
15861611
&& !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
1612+
&& ctx != UnusedDelimsCtx::MethodReceiver
15871613
&& (ctx != UnusedDelimsCtx::AnonConst
15881614
|| (matches!(expr.kind, ast::ExprKind::Lit(_))
15891615
&& !expr.span.from_expansion()))

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.

library/coretests/tests/floats/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,13 +770,13 @@ float_test! {
770770
assert_biteq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.);
771771
assert_biteq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.);
772772
assert_biteq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.);
773-
assert_biteq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
774-
assert_biteq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
773+
assert_biteq!(Float::MIN_POSITIVE.midpoint(Float::MAX), Float::MAX / 2.);
774+
assert_biteq!(Float::MIN_POSITIVE.midpoint(-Float::MAX), -Float::MAX / 2.);
775775
assert_biteq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
776776
assert_biteq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
777777
assert_biteq!(Float::MAX.midpoint(Float::MAX), Float::MAX);
778778
assert_biteq!(
779-
(Float::MIN_POSITIVE).midpoint(Float::MIN_POSITIVE),
779+
Float::MIN_POSITIVE.midpoint(Float::MIN_POSITIVE),
780780
Float::MIN_POSITIVE
781781
);
782782
assert_biteq!(
@@ -1175,7 +1175,7 @@ float_test! {
11751175
assert_biteq!((-Float::MAX_SUBNORMAL).next_down(), -Float::MIN_POSITIVE_NORMAL);
11761176
assert_biteq!((-Float::TINY).next_down(), -Float::TINY_UP);
11771177
assert_biteq!((-Float::ZERO).next_down(), -Float::TINY);
1178-
assert_biteq!((Float::ZERO).next_down(), -Float::TINY);
1178+
assert_biteq!(Float::ZERO.next_down(), -Float::TINY);
11791179
assert_biteq!(Float::TINY.next_down(), Float::ZERO);
11801180
assert_biteq!(Float::TINY_UP.next_down(), Float::TINY);
11811181
assert_biteq!(Float::MIN_POSITIVE_NORMAL.next_down(), Float::MAX_SUBNORMAL);

library/coretests/tests/time.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ fn div_duration_f32() {
264264
// These tests demonstrate it doesn't panic with extreme values.
265265
// Accuracy of the computed value is not a huge concern, we know floats don't work well
266266
// at these extremes.
267-
assert!((Duration::MAX).div_duration_f32(Duration::NANOSECOND) > 10.0f32.powf(28.0));
268-
assert!((Duration::NANOSECOND).div_duration_f32(Duration::MAX) < 0.1);
267+
assert!(Duration::MAX.div_duration_f32(Duration::NANOSECOND) > 10.0f32.powf(28.0));
268+
assert!(Duration::NANOSECOND.div_duration_f32(Duration::MAX) < 0.1);
269269
}
270270

271271
#[test]
@@ -277,8 +277,8 @@ fn div_duration_f64() {
277277
// These tests demonstrate it doesn't panic with extreme values.
278278
// Accuracy of the computed value is not a huge concern, we know floats don't work well
279279
// at these extremes.
280-
assert!((Duration::MAX).div_duration_f64(Duration::NANOSECOND) > 10.0f64.powf(28.0));
281-
assert!((Duration::NANOSECOND).div_duration_f64(Duration::MAX) < 0.1);
280+
assert!(Duration::MAX.div_duration_f64(Duration::NANOSECOND) > 10.0f64.powf(28.0));
281+
assert!(Duration::NANOSECOND.div_duration_f64(Duration::MAX) < 0.1);
282282
}
283283

284284
#[test]

src/tools/miri/tests/pass/u128.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ fn main() {
5757
// common traits
5858
assert_eq!(x, b(x.clone()));
5959
// overflow checks
60-
assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
61-
assert_eq!((k).checked_mul(k), None);
60+
assert_eq!(z.checked_mul(z), Some(0x734C_C2F2_A521));
61+
assert_eq!(k.checked_mul(k), None);
6262
let l: u128 = b(u128::MAX - 10);
6363
let o: u128 = b(17);
6464
assert_eq!(l.checked_add(b(11)), None);

src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub fn intern_const_ref<'a>(
9696
BuiltinUint::U16 => Box::new((i as u16).to_le_bytes()),
9797
BuiltinUint::U32 => Box::new((i as u32).to_le_bytes()),
9898
BuiltinUint::U64 => Box::new((i as u64).to_le_bytes()),
99-
BuiltinUint::U128 => Box::new((i).to_le_bytes()),
99+
BuiltinUint::U128 => Box::new(i.to_le_bytes()),
100100
BuiltinUint::Usize => Box::new((i as usize).to_le_bytes()),
101101
},
102102
_ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
@@ -136,7 +136,7 @@ pub fn intern_const_ref<'a>(
136136
BuiltinInt::I16 => Box::new((i as i16).to_le_bytes()),
137137
BuiltinInt::I32 => Box::new((i as i32).to_le_bytes()),
138138
BuiltinInt::I64 => Box::new((i as i64).to_le_bytes()),
139-
BuiltinInt::I128 => Box::new((i).to_le_bytes()),
139+
BuiltinInt::I128 => Box::new(i.to_le_bytes()),
140140
BuiltinInt::Isize => Box::new((i as isize).to_le_bytes()),
141141
},
142142
_ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),

src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ impl<'db> MirLowerCtx<'_, 'db> {
336336
id,
337337
mode,
338338
next_place,
339-
(slice).into(),
339+
slice.into(),
340340
current,
341341
current_else,
342342
)?;

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

0 commit comments

Comments
 (0)