@@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
1111use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1212use std:: f32:: consts as f32_consts;
1313use std:: f64:: consts as f64_consts;
14- use sugg:: Sugg ;
14+ use sugg:: { format_numeric_literal , Sugg } ;
1515use syntax:: ast;
1616
1717declare_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> {
187187fn 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