@@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
11
11
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
12
12
use std:: f32:: consts as f32_consts;
13
13
use std:: f64:: consts as f64_consts;
14
- use sugg:: Sugg ;
14
+ use sugg:: { format_numeric_literal , Sugg } ;
15
15
use syntax:: ast;
16
16
17
17
declare_clippy_lint ! {
@@ -159,23 +159,23 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
159
159
}
160
160
}
161
161
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.
166
166
#[ 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 > {
168
168
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 )
172
172
} else {
173
173
None
174
174
}
175
175
} ,
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 )
179
179
} else {
180
180
None
181
181
}
@@ -187,15 +187,13 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
187
187
fn check_powf ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > , args : & [ Expr < ' _ > ] ) {
188
188
// Check receiver
189
189
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"
194
192
} else if F32 ( 2.0 ) == value || F64 ( 2.0 ) == value {
195
- method = "exp2" ;
193
+ "exp2"
196
194
} else {
197
195
return ;
198
- }
196
+ } ;
199
197
200
198
span_lint_and_sugg (
201
199
cx,
@@ -210,38 +208,36 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
210
208
211
209
// Check argument
212
210
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
+ )
219
216
} 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
+ )
222
221
} 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
+ (
227
223
"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
+ )
234
230
} else {
235
231
return ;
236
- }
232
+ } ;
237
233
238
234
span_lint_and_sugg (
239
235
cx,
240
236
SUBOPTIMAL_FLOPS ,
241
237
expr. span ,
242
238
help,
243
239
"consider using" ,
244
- format ! ( "{}.{}()" , Sugg :: hir ( cx , & args [ 0 ] , ".." ) , method ) ,
240
+ suggestion ,
245
241
Applicability :: MachineApplicable ,
246
242
) ;
247
243
}
0 commit comments