Skip to content

Commit

Permalink
Lint on ambiguous precedence expressions even if method calls are odd
Browse files Browse the repository at this point in the history
  • Loading branch information
Urgau committed Nov 17, 2023
1 parent 057e4d7 commit a5c0684
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 83 deletions.
33 changes: 5 additions & 28 deletions compiler/rustc_lint/src/precedence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,6 @@ use rustc_span::source_map::Spanned;
use crate::lints::{PrecedenceDiag, PrecedenceUnarySuggestion, PrecedenceUnwarySuggestion};
use crate::{EarlyContext, EarlyLintPass, LintContext};

// List of functions `f(x)` where `f(-x)=-f(x)` so the
// precedence doens't matter.
const ALLOWED_ODD_FUNCTIONS: [&str; 14] = [
"asin",
"asinh",
"atan",
"atanh",
"cbrt",
"fract",
"round",
"signum",
"sin",
"sinh",
"tan",
"tanh",
"to_degrees",
"to_radians",
];

declare_lint! {
/// The `ambiguous_precedence` lint checks for operations where
/// precedence may be unclear and suggests adding parentheses.
Expand Down Expand Up @@ -86,19 +67,15 @@ impl EarlyLintPass for Precedence {
);
}

if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind {
if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind
&& let ExprKind::MethodCall(..) = operand.kind
{
let mut arg = operand;

let mut all_odd = true;
while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind {
let seg_str = seg.ident.name.as_str();
all_odd &=
ALLOWED_ODD_FUNCTIONS.iter().any(|odd_function| **odd_function == *seg_str);
while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind {
arg = receiver;
}

if !all_odd
&& let ExprKind::Lit(lit) = &arg.kind
if let ExprKind::Lit(lit) = &arg.kind
&& let LitKind::Integer | LitKind::Float = &lit.kind
&& !arg.span.from_expansion()
{
Expand Down
43 changes: 16 additions & 27 deletions tests/ui/lint/precedence.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ fn main() {
//~^ WARN unary minus has lower precedence than method call
let _ = -(1f32.abs());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1f64.asin());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1f64.asinh());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1f64.tan());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1f64.tanh());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1.0_f64.cos().cos());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1.0_f64.cos().sin());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1.0_f64.sin().cos());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1f64.sin().sin());
//~^ WARN unary minus has lower precedence than method call

// These should not trigger an error
let _ = (-1i32).abs();
Expand All @@ -30,31 +46,4 @@ fn main() {
let _ = -(1f32).abs();
let _ = -(1i32.abs());
let _ = -(1f32.abs());

// Odd functions should not trigger an error
let _ = -1f64.asin();
let _ = -1f64.asinh();
let _ = -1f64.atan();
let _ = -1f64.atanh();
let _ = -1f64.cbrt();
let _ = -1f64.fract();
let _ = -1f64.round();
let _ = -1f64.signum();
let _ = -1f64.sin();
let _ = -1f64.sinh();
let _ = -1f64.tan();
let _ = -1f64.tanh();
let _ = -1f64.to_degrees();
let _ = -1f64.to_radians();

// Chains containing any non-odd function should trigger (issue clippy#5924)
let _ = -(1.0_f64.cos().cos());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1.0_f64.cos().sin());
//~^ WARN unary minus has lower precedence than method call
let _ = -(1.0_f64.sin().cos());
//~^ WARN unary minus has lower precedence than method call

// Chains of odd functions shouldn't trigger
let _ = -1f64.sin().sin();
}
37 changes: 13 additions & 24 deletions tests/ui/lint/precedence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,28 @@ fn main() {
//~^ WARN unary minus has lower precedence than method call
let _ = -1f32.abs();
//~^ WARN unary minus has lower precedence than method call

// These should not trigger an error
let _ = (-1i32).abs();
let _ = (-1f32).abs();
let _ = -(1i32).abs();
let _ = -(1f32).abs();
let _ = -(1i32.abs());
let _ = -(1f32.abs());

// Odd functions should not trigger an error
let _ = -1f64.asin();
//~^ WARN unary minus has lower precedence than method call
let _ = -1f64.asinh();
let _ = -1f64.atan();
let _ = -1f64.atanh();
let _ = -1f64.cbrt();
let _ = -1f64.fract();
let _ = -1f64.round();
let _ = -1f64.signum();
let _ = -1f64.sin();
let _ = -1f64.sinh();
//~^ WARN unary minus has lower precedence than method call
let _ = -1f64.tan();
//~^ WARN unary minus has lower precedence than method call
let _ = -1f64.tanh();
let _ = -1f64.to_degrees();
let _ = -1f64.to_radians();

// Chains containing any non-odd function should trigger (issue clippy#5924)
//~^ WARN unary minus has lower precedence than method call
let _ = -1.0_f64.cos().cos();
//~^ WARN unary minus has lower precedence than method call
let _ = -1.0_f64.cos().sin();
//~^ WARN unary minus has lower precedence than method call
let _ = -1.0_f64.sin().cos();
//~^ WARN unary minus has lower precedence than method call

// Chains of odd functions shouldn't trigger
let _ = -1f64.sin().sin();
//~^ WARN unary minus has lower precedence than method call

// These should not trigger an error
let _ = (-1i32).abs();
let _ = (-1f32).abs();
let _ = -(1i32).abs();
let _ = -(1f32).abs();
let _ = -(1i32.abs());
let _ = -(1f32.abs());
}
63 changes: 59 additions & 4 deletions tests/ui/lint/precedence.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,51 @@ LL | let _ = -(1f32.abs());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:51:13
--> $DIR/precedence.rs:25:13
|
LL | let _ = -1f64.asin();
| ^^^^^^^^^^^^
|
help: consider adding parentheses to clarify your intent
|
LL | let _ = -(1f64.asin());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:27:13
|
LL | let _ = -1f64.asinh();
| ^^^^^^^^^^^^^
|
help: consider adding parentheses to clarify your intent
|
LL | let _ = -(1f64.asinh());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:29:13
|
LL | let _ = -1f64.tan();
| ^^^^^^^^^^^
|
help: consider adding parentheses to clarify your intent
|
LL | let _ = -(1f64.tan());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:31:13
|
LL | let _ = -1f64.tanh();
| ^^^^^^^^^^^^
|
help: consider adding parentheses to clarify your intent
|
LL | let _ = -(1f64.tanh());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:33:13
|
LL | let _ = -1.0_f64.cos().cos();
| ^^^^^^^^^^^^^^^^^^^^
Expand All @@ -121,7 +165,7 @@ LL | let _ = -(1.0_f64.cos().cos());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:53:13
--> $DIR/precedence.rs:35:13
|
LL | let _ = -1.0_f64.cos().sin();
| ^^^^^^^^^^^^^^^^^^^^
Expand All @@ -132,7 +176,7 @@ LL | let _ = -(1.0_f64.cos().sin());
| + +

warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:55:13
--> $DIR/precedence.rs:37:13
|
LL | let _ = -1.0_f64.sin().cos();
| ^^^^^^^^^^^^^^^^^^^^
Expand All @@ -142,5 +186,16 @@ help: consider adding parentheses to clarify your intent
LL | let _ = -(1.0_f64.sin().cos());
| + +

warning: 13 warnings emitted
warning: unary minus has lower precedence than method call
--> $DIR/precedence.rs:39:13
|
LL | let _ = -1f64.sin().sin();
| ^^^^^^^^^^^^^^^^^
|
help: consider adding parentheses to clarify your intent
|
LL | let _ = -(1f64.sin().sin());
| + +

warning: 18 warnings emitted

0 comments on commit a5c0684

Please sign in to comment.