@@ -6,7 +6,6 @@ use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, Lin
6
6
use rustc:: { declare_lint_pass, declare_tool_lint} ;
7
7
use rustc_data_structures:: fx:: FxHashMap ;
8
8
use rustc_errors:: Applicability ;
9
- use std:: char;
10
9
use syntax:: ast:: * ;
11
10
use syntax:: source_map:: Span ;
12
11
use syntax:: visit:: { walk_expr, FnKind , Visitor } ;
@@ -391,92 +390,102 @@ impl EarlyLintPass for MiscEarlyLints {
391
390
392
391
impl MiscEarlyLints {
393
392
fn check_lit ( self , cx : & EarlyContext < ' _ > , lit : & Lit ) {
394
- if_chain ! {
395
- if let LitKind :: Int ( value, ..) = lit. node;
396
- if let Some ( src) = snippet_opt( cx, lit. span) ;
397
- if let Some ( firstch) = src. chars( ) . next( ) ;
398
- if char :: to_digit( firstch, 10 ) . is_some( ) ;
399
- then {
400
- let mut prev = '\0' ;
401
- for ( idx, ch) in src. chars( ) . enumerate( ) {
402
- if ch == 'i' || ch == 'u' {
403
- if prev != '_' {
404
- span_lint_and_sugg(
405
- cx,
406
- UNSEPARATED_LITERAL_SUFFIX ,
407
- lit. span,
408
- "integer type suffix should be separated by an underscore" ,
409
- "add an underscore" ,
410
- format!( "{}_{}" , & src[ 0 ..idx] , & src[ idx..] ) ,
411
- Applicability :: MachineApplicable ,
412
- ) ;
413
- }
414
- break ;
415
- }
416
- prev = ch;
393
+ // The `line!()` macro is compiler built-in and a special case for these lints.
394
+ let lit_snip = match snippet_opt ( cx, lit. span ) {
395
+ Some ( snip) => {
396
+ if snip. contains ( '!' ) {
397
+ return ;
417
398
}
418
- if src. starts_with( "0x" ) {
419
- let mut seen = ( false , false ) ;
420
- for ch in src. chars( ) {
421
- match ch {
422
- 'a' ..= 'f' => seen. 0 = true ,
423
- 'A' ..= 'F' => seen. 1 = true ,
424
- 'i' | 'u' => break , // start of suffix already
425
- _ => ( )
426
- }
427
- }
428
- if seen. 0 && seen. 1 {
429
- span_lint( cx, MIXED_CASE_HEX_LITERALS , lit. span,
430
- "inconsistent casing in hexadecimal literal" ) ;
399
+ snip
400
+ } ,
401
+ _ => return ,
402
+ } ;
403
+
404
+ if let LitKind :: Int ( value, lit_int_type) = lit. node {
405
+ let suffix = match lit_int_type {
406
+ LitIntType :: Signed ( ty) => ty. ty_to_string ( ) ,
407
+ LitIntType :: Unsigned ( ty) => ty. ty_to_string ( ) ,
408
+ LitIntType :: Unsuffixed => "" ,
409
+ } ;
410
+
411
+ let maybe_last_sep_idx = lit_snip. len ( ) - suffix. len ( ) - 1 ;
412
+ // Do not lint when literal is unsuffixed.
413
+ if !suffix. is_empty ( ) && lit_snip. as_bytes ( ) [ maybe_last_sep_idx] != b'_' {
414
+ span_lint_and_sugg (
415
+ cx,
416
+ UNSEPARATED_LITERAL_SUFFIX ,
417
+ lit. span ,
418
+ "integer type suffix should be separated by an underscore" ,
419
+ "add an underscore" ,
420
+ format ! ( "{}_{}" , & lit_snip[ ..=maybe_last_sep_idx] , suffix) ,
421
+ Applicability :: MachineApplicable ,
422
+ ) ;
423
+ }
424
+
425
+ if lit_snip. starts_with ( "0x" ) {
426
+ let mut seen = ( false , false ) ;
427
+ for ch in lit_snip. as_bytes ( ) [ 2 ..=maybe_last_sep_idx] . iter ( ) {
428
+ match ch {
429
+ b'a' ..=b'f' => {
430
+ seen. 0 = true ;
431
+ if seen. 1 {
432
+ break ;
433
+ }
434
+ } ,
435
+ b'A' ..=b'F' => {
436
+ seen. 1 = true ;
437
+ if seen. 0 {
438
+ break ;
439
+ }
440
+ } ,
441
+ _ => { } ,
431
442
}
432
- } else if src. starts_with( "0b" ) || src. starts_with( "0o" ) {
433
- /* nothing to do */
434
- } else if value != 0 && src. starts_with( '0' ) {
435
- span_lint_and_then( cx,
436
- ZERO_PREFIXED_LITERAL ,
437
- lit. span,
438
- "this is a decimal constant" ,
439
- |db| {
443
+ }
444
+ if seen. 0 && seen. 1 {
445
+ span_lint (
446
+ cx,
447
+ MIXED_CASE_HEX_LITERALS ,
448
+ lit. span ,
449
+ "inconsistent casing in hexadecimal literal" ,
450
+ ) ;
451
+ }
452
+ } else if lit_snip. starts_with ( "0b" ) || lit_snip. starts_with ( "0o" ) {
453
+ /* nothing to do */
454
+ } else if value != 0 && lit_snip. starts_with ( '0' ) {
455
+ span_lint_and_then (
456
+ cx,
457
+ ZERO_PREFIXED_LITERAL ,
458
+ lit. span ,
459
+ "this is a decimal constant" ,
460
+ |db| {
440
461
db. span_suggestion (
441
462
lit. span ,
442
- "if you mean to use a decimal constant, remove the `0` to remove confusion" ,
443
- src . trim_start_matches( |c| c == '_' || c == '0' ) . to_string( ) ,
463
+ "if you mean to use a decimal constant, remove the `0` to avoid confusion" ,
464
+ lit_snip . trim_start_matches ( |c| c == '_' || c == '0' ) . to_string ( ) ,
444
465
Applicability :: MaybeIncorrect ,
445
466
) ;
446
467
db. span_suggestion (
447
468
lit. span ,
448
469
"if you mean to use an octal constant, use `0o`" ,
449
- format!( "0o{}" , src . trim_start_matches( |c| c == '_' || c == '0' ) ) ,
470
+ format ! ( "0o{}" , lit_snip . trim_start_matches( |c| c == '_' || c == '0' ) ) ,
450
471
Applicability :: MaybeIncorrect ,
451
472
) ;
452
- } ) ;
453
- }
473
+ } ,
474
+ ) ;
454
475
}
455
- }
456
- if_chain ! {
457
- if let LitKind :: Float ( ..) = lit. node;
458
- if let Some ( src) = snippet_opt( cx, lit. span) ;
459
- if let Some ( firstch) = src. chars( ) . next( ) ;
460
- if char :: to_digit( firstch, 10 ) . is_some( ) ;
461
- then {
462
- let mut prev = '\0' ;
463
- for ( idx, ch) in src. chars( ) . enumerate( ) {
464
- if ch == 'f' {
465
- if prev != '_' {
466
- span_lint_and_sugg(
467
- cx,
468
- UNSEPARATED_LITERAL_SUFFIX ,
469
- lit. span,
470
- "float type suffix should be separated by an underscore" ,
471
- "add an underscore" ,
472
- format!( "{}_{}" , & src[ 0 ..idx] , & src[ idx..] ) ,
473
- Applicability :: MachineApplicable ,
474
- ) ;
475
- }
476
- break ;
477
- }
478
- prev = ch;
479
- }
476
+ } else if let LitKind :: Float ( _, float_ty) = lit. node {
477
+ let suffix = float_ty. ty_to_string ( ) ;
478
+ let maybe_last_sep_idx = lit_snip. len ( ) - suffix. len ( ) - 1 ;
479
+ if lit_snip. as_bytes ( ) [ maybe_last_sep_idx] != b'_' {
480
+ span_lint_and_sugg (
481
+ cx,
482
+ UNSEPARATED_LITERAL_SUFFIX ,
483
+ lit. span ,
484
+ "float type suffix should be separated by an underscore" ,
485
+ "add an underscore" ,
486
+ format ! ( "{}_{}" , & lit_snip[ ..=maybe_last_sep_idx] , suffix) ,
487
+ Applicability :: MachineApplicable ,
488
+ ) ;
480
489
}
481
490
}
482
491
}
0 commit comments