Skip to content

Commit bc706e3

Browse files
Fix powi suggestion and add general improvements
1 parent 6dacb1a commit bc706e3

File tree

1 file changed

+34
-38
lines changed

1 file changed

+34
-38
lines changed

clippy_lints/src/floating_point_arithmetic.rs

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
1111
use rustc_session::{declare_lint_pass, declare_tool_lint};
1212
use std::f32::consts as f32_consts;
1313
use std::f64::consts as f64_consts;
14-
use sugg::Sugg;
14+
use sugg::{format_numeric_literal, Sugg};
1515
use syntax::ast;
1616

1717
declare_clippy_lint! {
@@ -159,23 +159,23 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
159159
}
160160
}
161161

162-
// Returns an integer if the float constant is a whole number and it
163-
// can be converted to an integer without loss
164-
// TODO: Add a better check to determine whether the float can be
165-
// casted without loss
162+
// Returns an integer if the float constant is a whole number and it can be
163+
// converted to an integer without loss of precision. For now we only check
164+
// ranges [-16777215, 16777216) for type f32 as whole number floats outside
165+
// this range are lossy and ambiguous.
166166
#[allow(clippy::cast_possible_truncation)]
167-
fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
167+
fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
168168
match value {
169-
F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => {
170-
if *num > -16_777_217.0 && *num < 16_777_217.0 {
171-
Some(num.round() as i64)
169+
F32(num) if num.fract() == 0.0 => {
170+
if (-16_777_215.0..16_777_216.0).contains(num) {
171+
Some(num.round() as i32)
172172
} else {
173173
None
174174
}
175175
},
176-
F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => {
177-
if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 {
178-
Some(num.round() as i64)
176+
F64(num) if num.fract() == 0.0 => {
177+
if (-2_147_483_648.0..2_147_483_648.0).contains(num) {
178+
Some(num.round() as i32)
179179
} else {
180180
None
181181
}
@@ -187,15 +187,13 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
187187
fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
188188
// Check receiver
189189
if let Some((value, _)) = constant(cx, cx.tables, &args[0]) {
190-
let method;
191-
192-
if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
193-
method = "exp";
190+
let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
191+
"exp"
194192
} else if F32(2.0) == value || F64(2.0) == value {
195-
method = "exp2";
193+
"exp2"
196194
} else {
197195
return;
198-
}
196+
};
199197

200198
span_lint_and_sugg(
201199
cx,
@@ -210,38 +208,36 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
210208

211209
// Check argument
212210
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
213-
let help;
214-
let method;
215-
216-
if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
217-
help = "square-root of a number can be computed more efficiently and accurately";
218-
method = "sqrt";
211+
let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
212+
(
213+
"square-root of a number can be computed more efficiently and accurately",
214+
format!("{}.sqrt()", Sugg::hir(cx, &args[0], ".."))
215+
)
219216
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
220-
help = "cube-root of a number can be computed more accurately";
221-
method = "cbrt";
217+
(
218+
"cube-root of a number can be computed more accurately",
219+
format!("{}.cbrt()", Sugg::hir(cx, &args[0], ".."))
220+
)
222221
} else if let Some(exponent) = get_integer_from_float_constant(&value) {
223-
span_lint_and_sugg(
224-
cx,
225-
SUBOPTIMAL_FLOPS,
226-
expr.span,
222+
(
227223
"exponentiation with integer powers can be computed more efficiently",
228-
"consider using",
229-
format!("{}.powi({})", Sugg::hir(cx, &args[0], ".."), exponent),
230-
Applicability::MachineApplicable,
231-
);
232-
233-
return;
224+
format!(
225+
"{}.powi({})",
226+
Sugg::hir(cx, &args[0], ".."),
227+
format_numeric_literal(&exponent.to_string(), None, false)
228+
)
229+
)
234230
} else {
235231
return;
236-
}
232+
};
237233

238234
span_lint_and_sugg(
239235
cx,
240236
SUBOPTIMAL_FLOPS,
241237
expr.span,
242238
help,
243239
"consider using",
244-
format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method),
240+
suggestion,
245241
Applicability::MachineApplicable,
246242
);
247243
}

0 commit comments

Comments
 (0)