Skip to content
Draft
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
34 changes: 30 additions & 4 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
enum UnusedDelimsCtx {
FunctionArg,
MethodArg,
MethodReceiver,
AssignedValue,
AssignedValueLetElse,
IfCond,
Expand All @@ -645,6 +646,7 @@ impl From<UnusedDelimsCtx> for &'static str {
match ctx {
UnusedDelimsCtx::FunctionArg => "function argument",
UnusedDelimsCtx::MethodArg => "method argument",
UnusedDelimsCtx::MethodReceiver => "method receiver",
UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
"assigned value"
}
Expand Down Expand Up @@ -710,6 +712,16 @@ trait UnusedDelimLint {
}
}

// For method receivers, only lint simple path expressions like `(x).method()`.
// Keep parens for all other cases to avoid false positives with complex expressions
// like `(1..10).sum()`, `(*ptr).method()`, `({ block }).method()`, etc.
// Only lint simple variable names like `(x).method()`
if ctx == UnusedDelimsCtx::MethodReceiver {
if !matches!(inner.kind, ast::ExprKind::Path(None, _)) {
return true;
}
}

// Check it's range in LetScrutineeExpr
if let ast::ExprKind::Range(..) = inner.kind
&& matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
Expand Down Expand Up @@ -976,13 +988,15 @@ trait UnusedDelimLint {
}
// either function/method call, or something this lint doesn't care about
ref call_or_other => {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
let (args_to_check, ctx, receiver) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg, None),
MethodCall(ref call) => {
(&call.args[..], UnusedDelimsCtx::MethodArg, Some(&call.receiver))
}
Closure(ref closure)
if matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
{
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
(&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody, None)
}
// actual catch-all arm
_ => {
Expand All @@ -999,6 +1013,17 @@ trait UnusedDelimLint {
for arg in args_to_check {
self.check_unused_delims_expr(cx, arg, ctx, false, None, None, false);
}
if let Some(recv) = receiver {
self.check_unused_delims_expr(
cx,
recv,
UnusedDelimsCtx::MethodReceiver,
false,
None,
None,
false,
);
}
return;
}
};
Expand Down Expand Up @@ -1584,6 +1609,7 @@ impl UnusedDelimLint for UnusedBraces {
if let [stmt] = inner.stmts.as_slice()
&& let ast::StmtKind::Expr(ref expr) = stmt.kind
&& !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
&& ctx != UnusedDelimsCtx::MethodReceiver
&& (ctx != UnusedDelimsCtx::AnonConst
|| (matches!(expr.kind, ast::ExprKind::Lit(_))
&& !expr.span.from_expansion()))
Expand Down
2 changes: 1 addition & 1 deletion library/compiler-builtins/libm/src/math/cbrt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ pub fn cbrt_round(x: f64, round: Round) -> FpResult<f64> {
let mut cvt4: u64 = y1.to_bits();
cvt4 = (cvt4 + (164 << 15)) & 0xffffffffffff0000u64;

if ((f64::from_bits(cvt4) - y1) - dy).abs() < hf64!("0x1p-60") || (zz).abs() == 1.0 {
if ((f64::from_bits(cvt4) - y1) - dy).abs() < hf64!("0x1p-60") || zz.abs() == 1.0 {
cvt3 = (cvt3 + (1u64 << 15)) & 0xffffffffffff0000u64;
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<T: PointeeSized> *const T {
@capture { ptr: *const u8 } -> bool:
// This use of `const_raw_ptr_comparison` has been explicitly blessed by t-lang.
if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] {
match (ptr).guaranteed_eq(null_mut()) {
match ptr.guaranteed_eq(null_mut()) {
Some(res) => res,
// To remain maximally conservative, we stop execution when we don't
// know whether the pointer is null or not.
Expand Down
8 changes: 4 additions & 4 deletions library/coretests/tests/floats/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,13 +770,13 @@ float_test! {
assert_biteq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.);
assert_biteq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.);
assert_biteq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.);
assert_biteq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
assert_biteq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
assert_biteq!(Float::MIN_POSITIVE.midpoint(Float::MAX), Float::MAX / 2.);
assert_biteq!(Float::MIN_POSITIVE.midpoint(-Float::MAX), -Float::MAX / 2.);
assert_biteq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
assert_biteq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
assert_biteq!(Float::MAX.midpoint(Float::MAX), Float::MAX);
assert_biteq!(
(Float::MIN_POSITIVE).midpoint(Float::MIN_POSITIVE),
Float::MIN_POSITIVE.midpoint(Float::MIN_POSITIVE),
Float::MIN_POSITIVE
);
assert_biteq!(
Expand Down Expand Up @@ -1175,7 +1175,7 @@ float_test! {
assert_biteq!((-Float::MAX_SUBNORMAL).next_down(), -Float::MIN_POSITIVE_NORMAL);
assert_biteq!((-Float::TINY).next_down(), -Float::TINY_UP);
assert_biteq!((-Float::ZERO).next_down(), -Float::TINY);
assert_biteq!((Float::ZERO).next_down(), -Float::TINY);
assert_biteq!(Float::ZERO.next_down(), -Float::TINY);
assert_biteq!(Float::TINY.next_down(), Float::ZERO);
assert_biteq!(Float::TINY_UP.next_down(), Float::TINY);
assert_biteq!(Float::MIN_POSITIVE_NORMAL.next_down(), Float::MAX_SUBNORMAL);
Expand Down
8 changes: 4 additions & 4 deletions library/coretests/tests/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ fn div_duration_f32() {
// These tests demonstrate it doesn't panic with extreme values.
// Accuracy of the computed value is not a huge concern, we know floats don't work well
// at these extremes.
assert!((Duration::MAX).div_duration_f32(Duration::NANOSECOND) > 10.0f32.powf(28.0));
assert!((Duration::NANOSECOND).div_duration_f32(Duration::MAX) < 0.1);
assert!(Duration::MAX.div_duration_f32(Duration::NANOSECOND) > 10.0f32.powf(28.0));
assert!(Duration::NANOSECOND.div_duration_f32(Duration::MAX) < 0.1);
}

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

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/pass/u128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ fn main() {
// common traits
assert_eq!(x, b(x.clone()));
// overflow checks
assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
assert_eq!((k).checked_mul(k), None);
assert_eq!(z.checked_mul(z), Some(0x734C_C2F2_A521));
assert_eq!(k.checked_mul(k), None);
let l: u128 = b(u128::MAX - 10);
let o: u128 = b(17);
assert_eq!(l.checked_add(b(11)), None);
Expand Down
4 changes: 2 additions & 2 deletions src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub fn intern_const_ref<'a>(
BuiltinUint::U16 => Box::new((i as u16).to_le_bytes()),
BuiltinUint::U32 => Box::new((i as u32).to_le_bytes()),
BuiltinUint::U64 => Box::new((i as u64).to_le_bytes()),
BuiltinUint::U128 => Box::new((i).to_le_bytes()),
BuiltinUint::U128 => Box::new(i.to_le_bytes()),
BuiltinUint::Usize => Box::new((i as usize).to_le_bytes()),
},
_ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
Expand Down Expand Up @@ -136,7 +136,7 @@ pub fn intern_const_ref<'a>(
BuiltinInt::I16 => Box::new((i as i16).to_le_bytes()),
BuiltinInt::I32 => Box::new((i as i32).to_le_bytes()),
BuiltinInt::I64 => Box::new((i as i64).to_le_bytes()),
BuiltinInt::I128 => Box::new((i).to_le_bytes()),
BuiltinInt::I128 => Box::new(i.to_le_bytes()),
BuiltinInt::Isize => Box::new((i as isize).to_le_bytes()),
},
_ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ impl<'db> MirLowerCtx<'_, 'db> {
id,
mode,
next_place,
(slice).into(),
slice.into(),
current,
current_else,
)?;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/test-float-parse/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Constants {
let neg_inf_cutoff = -&inf_cutoff;

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

Expand Down
26 changes: 26 additions & 0 deletions tests/ui/lint/unused-parens-method-receiver-issue-151985.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ run-rustfix

#![deny(unused_parens)]

struct Thing;
impl Thing {
fn method(self) {}
}

fn main() {
// Unnecessary parens - should warn
let x = Thing;
x.method(); //~ ERROR unnecessary parentheses around method receiver

// Necessary parens - should NOT warn
let _ = (1..10).sum::<i32>(); // Range expression
let _ = (1_i32 + 2).abs(); // Binary expression
let _ = (-1_i32).abs(); // Unary expression
let _ = (true as i32).abs(); // Cast expression
let _ = (&42).clone(); // AddrOf expression
let _ = (&mut 42).clone(); // AddrOf mut expression

// Block expressions - should NOT warn
let _ = ({ 1_i32 }).abs(); // Block expression
let _ = (unsafe { std::mem::zeroed::<i32>() }).abs(); // Unsafe block expression
}
29 changes: 29 additions & 0 deletions tests/ui/lint/unused-parens-method-receiver-issue-151985.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//@ run-rustfix

#![deny(unused_parens)]

struct Thing;
impl Thing {
fn method(self) {}
}

fn main() {
// Unnecessary parens - should warn
let x = Thing;
(x).method(); //~ ERROR unnecessary parentheses around method receiver

// Necessary parens - should NOT warn
let _ = (1..10).sum::<i32>(); // Range expression
let _ = (1_i32 + 2).abs(); // Binary expression
let _ = (-1_i32).abs(); // Unary expression
let _ = (true as i32).abs(); // Cast expression
let _ = (&42).clone(); // AddrOf expression
let _ = (&mut 42).clone(); // AddrOf mut expression

// Block expressions - should NOT warn
let _ = ({ 1_i32 }).abs(); // Block expression
let _ = (unsafe { std::mem::zeroed::<i32>() }).abs(); // Unsafe block expression

// lint for path with multiple segments
let _ = (Float::MIN_POSITIVE).midpoint(-Float::MAX);
}
19 changes: 19 additions & 0 deletions tests/ui/lint/unused-parens-method-receiver-issue-151985.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error: unnecessary parentheses around method receiver
--> $DIR/unused-parens-method-receiver-issue-151985.rs:13:5
|
LL | (x).method();
| ^ ^
|
note: the lint level is defined here
--> $DIR/unused-parens-method-receiver-issue-151985.rs:3:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
help: remove these parentheses
|
LL - (x).method();
LL + x.method();
|

error: aborting due to 1 previous error

Loading