Skip to content

Commit

Permalink
Auto merge of #9577 - kraktus:unnecessary_cast, r=llogiq
Browse files Browse the repository at this point in the history
[`unnecessary_cast`] add parenthesis when negative number uses a method

fix #9563

The issue was probably introduced by 90fe3be

changelog: [`unnecessary_cast`] add parenthesis when negative number uses a method

r? llogiq
  • Loading branch information
bors committed Oct 2, 2022
2 parents d6d5ecd + 90b446f commit ac12011
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 9 deletions.
33 changes: 25 additions & 8 deletions clippy_lints/src/casts/unnecessary_cast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
Expand Down Expand Up @@ -85,22 +86,38 @@ pub(super) fn check<'tcx>(
false
}

fn lint_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &str, cast_from: Ty<'_>, cast_to: Ty<'_>) {
fn lint_unnecessary_cast(
cx: &LateContext<'_>,
expr: &Expr<'_>,
raw_literal_str: &str,
cast_from: Ty<'_>,
cast_to: Ty<'_>,
) {
let literal_kind_name = if cast_from.is_integral() { "integer" } else { "float" };
let replaced_literal;
let matchless = if literal_str.contains(['(', ')']) {
replaced_literal = literal_str.replace(['(', ')'], "");
&replaced_literal
} else {
literal_str
// first we remove all matches so `-(1)` become `-1`, and remove trailing dots, so `1.` become `1`
let literal_str = raw_literal_str
.replace(['(', ')'], "")
.trim_end_matches('.')
.to_string();
// we know need to check if the parent is a method call, to add parenthesis accordingly (eg:
// (-1).foo() instead of -1.foo())
let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
&& let ExprKind::MethodCall(..) = parent_expr.kind
&& literal_str.starts_with('-')
{
format!("({literal_str}_{cast_to})")

} else {
format!("{literal_str}_{cast_to}")
};

span_lint_and_sugg(
cx,
UNNECESSARY_CAST,
expr.span,
&format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
"try",
format!("{}_{cast_to}", matchless.trim_end_matches('.')),
sugg,
Applicability::MachineApplicable,
);
}
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/unnecessary_cast.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,10 @@ mod fixable {

let _ = -(1 + 1) as i64;
}

fn issue_9563() {
let _: f64 = (-8.0_f64).exp();
#[allow(clippy::precedence)]
let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
}
}
6 changes: 6 additions & 0 deletions tests/ui/unnecessary_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,10 @@ mod fixable {

let _ = -(1 + 1) as i64;
}

fn issue_9563() {
let _: f64 = (-8.0 as f64).exp();
#[allow(clippy::precedence)]
let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
}
}
14 changes: 13 additions & 1 deletion tests/ui/unnecessary_cast.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,17 @@ error: casting integer literal to `i64` is unnecessary
LL | let _: i64 = -(1) as i64;
| ^^^^^^^^^^^ help: try: `-1_i64`

error: aborting due to 27 previous errors
error: casting float literal to `f64` is unnecessary
--> $DIR/unnecessary_cast.rs:102:22
|
LL | let _: f64 = (-8.0 as f64).exp();
| ^^^^^^^^^^^^^ help: try: `(-8.0_f64)`

error: casting float literal to `f64` is unnecessary
--> $DIR/unnecessary_cast.rs:104:23
|
LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
| ^^^^^^^^^^^^ help: try: `8.0_f64`

error: aborting due to 29 previous errors

0 comments on commit ac12011

Please sign in to comment.