@@ -153,18 +153,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
153
153
if ( negative && v > max + 1 ) || ( !negative && v > max) {
154
154
if let Some ( repr_str) = get_bin_hex_repr ( cx, lit) {
155
155
let bits = int_ty_bits ( t, cx. sess ( ) . target . isize_ty ) ;
156
- let mut actually = v as i128 ;
157
- if bits < 128 {
158
- // v & 0b0..01..1, |1| = bits
159
- let trimmed = v & ( ( 1 << bits) - 1 ) ;
160
- actually = if v & ( 1 << ( bits - 1 ) ) == 0 {
161
- // positive
162
- trimmed as i128
163
- } else {
164
- // negative -> two's complement
165
- ( ( ( -1 as i128 as u128 ) << bits) | trimmed) as i128
166
- } ;
167
- }
156
+ let actually =
157
+ ( ( v << ( 128 - bits) ) as i128 ) >> ( 128 - bits) ;
168
158
let mut err = cx. struct_span_lint (
169
159
OVERFLOWING_LITERALS ,
170
160
e. span ,
@@ -175,15 +165,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
175
165
an `{:?}` and will become `{}{:?}`.",
176
166
repr_str, v, t, actually, t
177
167
) ) ;
178
- let sugg_ty = get_fitting_type (
168
+ let sugg_ty = get_type_suggestion (
179
169
& cx. tables . node_id_to_type ( e. hir_id ) . sty ,
180
170
v,
181
171
negative,
182
- ) . map_or ( String :: new ( ) , |ty| match ty {
183
- ty:: TyUint ( t) => format ! ( "Consider using `{:?}`" , t) ,
184
- ty:: TyInt ( t) => format ! ( "Consider using `{:?}`" , t) ,
185
- _ => String :: new ( ) ,
186
- } ) ;
172
+ ) ;
187
173
if !sugg_ty. is_empty ( ) {
188
174
err. help ( & sugg_ty) ;
189
175
}
@@ -221,24 +207,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
221
207
if let hir:: ExprCast ( ..) = parent_expr. node {
222
208
if let ty:: TyChar = cx. tables . expr_ty ( parent_expr) . sty {
223
209
let mut err = cx. struct_span_lint (
224
- OVERFLOWING_LITERALS ,
225
- parent_expr. span ,
226
- "only u8 can be casted into char" ,
227
- ) ;
228
- err. span_suggestion (
229
- parent_expr. span ,
230
- & "use a char literal instead" ,
231
- format ! ( "'\\ u{{{:X}}}'" , lit_val) ,
232
- ) ;
210
+ OVERFLOWING_LITERALS ,
211
+ parent_expr. span ,
212
+ "only u8 can be casted into char" ) ;
213
+ err. span_suggestion ( parent_expr. span ,
214
+ & "use a char literal instead" ,
215
+ format ! ( "'\\ u{{{:X}}}'" , lit_val) ) ;
233
216
err. emit ( ) ;
234
- return ;
217
+ return
235
218
}
236
219
}
237
220
}
238
221
if let Some ( repr_str) = get_bin_hex_repr ( cx, lit) {
239
222
let bits = uint_ty_bits ( t, cx. sess ( ) . target . usize_ty ) ;
240
- // u128 cannot be greater than max -> compiler error
241
- let actually = lit_val & ( ( 1 << bits) - 1 ) ;
223
+ let actually = ( lit_val << ( 128 - bits) ) >> ( 128 - bits) ;
242
224
let mut err = cx. struct_span_lint (
243
225
OVERFLOWING_LITERALS ,
244
226
e. span ,
@@ -249,19 +231,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
249
231
an `{:?}` and will become `{}{:?}`.",
250
232
repr_str, lit_val, t, actually, t
251
233
) ) ;
252
- let sugg_ty = get_fitting_type (
234
+ let sugg_ty = get_type_suggestion (
253
235
& cx. tables . node_id_to_type ( e. hir_id ) . sty ,
254
236
lit_val,
255
237
false ,
256
- ) . map_or (
257
- String :: new ( ) ,
258
- |ty| {
259
- if let ty:: TyUint ( t) = ty {
260
- format ! ( "Consider using `{:?}`" , t)
261
- } else {
262
- String :: new ( )
263
- }
264
- } ,
265
238
) ;
266
239
if !sugg_ty. is_empty ( ) {
267
240
err. help ( & sugg_ty) ;
@@ -279,19 +252,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
279
252
}
280
253
ty:: TyFloat ( t) => {
281
254
let is_infinite = match lit. node {
282
- ast:: LitKind :: Float ( v, _) | ast:: LitKind :: FloatUnsuffixed ( v) => match t
283
- {
284
- ast:: FloatTy :: F32 => v. as_str ( ) . parse ( ) . map ( f32:: is_infinite) ,
285
- ast:: FloatTy :: F64 => v. as_str ( ) . parse ( ) . map ( f64:: is_infinite) ,
286
- } ,
255
+ ast:: LitKind :: Float ( v, _) |
256
+ ast:: LitKind :: FloatUnsuffixed ( v) => {
257
+ match t {
258
+ ast:: FloatTy :: F32 => v. as_str ( ) . parse ( ) . map ( f32:: is_infinite) ,
259
+ ast:: FloatTy :: F64 => v. as_str ( ) . parse ( ) . map ( f64:: is_infinite) ,
260
+ }
261
+ }
287
262
_ => bug ! ( ) ,
288
263
} ;
289
264
if is_infinite == Ok ( true ) {
290
- cx. span_lint (
291
- OVERFLOWING_LITERALS ,
292
- e. span ,
293
- & format ! ( "literal out of range for {:?}" , t) ,
294
- ) ;
265
+ cx. span_lint ( OVERFLOWING_LITERALS ,
266
+ e. span ,
267
+ & format ! ( "literal out of range for {:?}" , t) ) ;
295
268
}
296
269
}
297
270
_ => ( ) ,
@@ -421,26 +394,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
421
394
}
422
395
423
396
fn get_bin_hex_repr ( cx : & LateContext , lit : & ast:: Lit ) -> Option < String > {
424
- if let Some ( src) = cx. sess ( ) . codemap ( ) . span_to_snippet ( lit. span ) . ok ( ) {
425
- if let Some ( firstch) = src. chars ( ) . next ( ) {
426
- if let Some ( 0 ) = char:: to_digit ( firstch, 10 ) {
427
- if let Some ( base) = src. chars ( ) . nth ( 1 ) {
428
- if base == 'x' || base == 'b' {
429
- return Some ( src) ;
430
- }
431
- }
432
- }
397
+ let src = cx. sess ( ) . codemap ( ) . span_to_snippet ( lit. span ) . ok ( ) ?;
398
+ let firstch = src. chars ( ) . next ( ) ?;
399
+
400
+ if let Some ( 0 ) = char:: to_digit ( firstch, 10 ) {
401
+ match src. chars ( ) . nth ( 1 ) {
402
+ Some ( 'x' ) | Some ( 'b' ) => return Some ( src) ,
403
+ _ => return None ,
433
404
}
434
405
}
435
406
436
407
None
437
408
}
438
409
439
- fn get_fitting_type < ' a > (
440
- t : & ty:: TypeVariants ,
441
- val : u128 ,
442
- negative : bool ,
443
- ) -> Option < ty:: TypeVariants < ' a > > {
410
+ // This function finds the next fitting type and generates a suggestion string.
411
+ // It searches for fitting types in the following way (`X < Y`):
412
+ // - `iX`: if literal fits in `uX` => `uX`, else => `iY`
413
+ // - `-iX` => `iY`
414
+ // - `uX` => `uY`
415
+ //
416
+ // No suggestion for: `isize`, `usize`.
417
+ fn get_type_suggestion < ' a > ( t : & ty:: TypeVariants , val : u128 , negative : bool ) -> String {
444
418
use syntax:: ast:: IntTy :: * ;
445
419
use syntax:: ast:: UintTy :: * ;
446
420
macro_rules! find_fit {
@@ -451,36 +425,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
451
425
match $ty {
452
426
$( $type => {
453
427
$( if !negative && val <= uint_ty_range( $utypes) . 1 {
454
- return Some ( ty :: TyUint ( $utypes) )
428
+ return format! ( "Consider using `{:?}`" , $utypes)
455
429
} ) *
456
430
$( if val <= int_ty_range( $itypes) . 1 as u128 + _neg {
457
- return Some ( ty :: TyInt ( $itypes) )
431
+ return format! ( "Consider using `{:?}`" , $itypes)
458
432
} ) *
459
- None
433
+ String :: new ( )
460
434
} , ) *
461
- _ => None
435
+ _ => String :: new ( )
462
436
}
463
437
}
464
438
}
465
439
}
466
- if let & ty:: TyInt ( i) = t {
467
- return find_fit ! ( i, val, negative,
468
- I8 => [ U8 ] => [ I16 , I32 , I64 , I128 ] ,
469
- I16 => [ U16 ] => [ I32 , I64 , I128 ] ,
470
- I32 => [ U32 ] => [ I64 , I128 ] ,
471
- I64 => [ U64 ] => [ I128 ] ,
472
- I128 => [ U128 ] => [ ] ) ;
473
- }
474
- if let & ty:: TyUint ( u) = t {
475
- return find_fit ! ( u, val, negative,
476
- U8 => [ U8 , U16 , U32 , U64 , U128 ] => [ ] ,
477
- U16 => [ U16 , U32 , U64 , U128 ] => [ ] ,
478
- U32 => [ U32 , U64 , U128 ] => [ ] ,
479
- U64 => [ U64 , U128 ] => [ ] ,
480
- U128 => [ U128 ] => [ ] ) ;
440
+ match t {
441
+ & ty:: TyInt ( i) => find_fit ! ( i, val, negative,
442
+ I8 => [ U8 ] => [ I16 , I32 , I64 , I128 ] ,
443
+ I16 => [ U16 ] => [ I32 , I64 , I128 ] ,
444
+ I32 => [ U32 ] => [ I64 , I128 ] ,
445
+ I64 => [ U64 ] => [ I128 ] ,
446
+ I128 => [ U128 ] => [ ] ) ,
447
+ & ty:: TyUint ( u) => find_fit ! ( u, val, negative,
448
+ U8 => [ U8 , U16 , U32 , U64 , U128 ] => [ ] ,
449
+ U16 => [ U16 , U32 , U64 , U128 ] => [ ] ,
450
+ U32 => [ U32 , U64 , U128 ] => [ ] ,
451
+ U64 => [ U64 , U128 ] => [ ] ,
452
+ U128 => [ U128 ] => [ ] ) ,
453
+ _ => String :: new ( ) ,
481
454
}
482
-
483
- None
484
455
}
485
456
}
486
457
}
0 commit comments