@@ -54,7 +54,7 @@ enum lint {
54
54
deprecated_pattern,
55
55
non_camel_case_types,
56
56
structural_records,
57
- type_limits,
57
+ type_limits,
58
58
59
59
managed_heap_memory,
60
60
owned_heap_memory,
@@ -187,10 +187,10 @@ fn get_lint_dict() -> lint_dict {
187
187
desc: ~"allow legacy modes",
188
188
default : forbid} ) ,
189
189
190
- ( ~"type_limits",
191
- @{ lint: type_limits,
192
- desc: ~"comparisons made useless by limits of the types involved",
193
- default : warn} )
190
+ ( ~"type_limits",
191
+ @{ lint: type_limits,
192
+ desc: ~"comparisons made useless by limits of the types involved",
193
+ default : warn} )
194
194
195
195
/* FIXME(#3266)--make liveness warnings lintable
196
196
(~"unused_variable",
@@ -403,7 +403,7 @@ fn check_item(i: @ast::item, cx: ty::ctxt) {
403
403
check_item_heap( cx, i) ;
404
404
check_item_structural_records( cx, i) ;
405
405
check_item_deprecated_modes( cx, i) ;
406
- check_item_type_limits( cx, i) ;
406
+ check_item_type_limits( cx, i) ;
407
407
}
408
408
409
409
// Take a visitor, and modify it so that it will not proceed past subitems.
@@ -438,105 +438,119 @@ fn check_item_while_true(cx: ty::ctxt, it: @ast::item) {
438
438
}
439
439
440
440
fn check_item_type_limits( cx: ty:: ctxt, it: @ast:: item) {
441
- pure fn is_valid<T : cmp:: Ord >( binop: ast:: binop, v: T , min: T , max: T ) -> bool {
442
- match binop {
443
- ast:: lt => v <= max,
444
- ast:: le => v < max,
445
- ast:: gt => v >= min,
446
- ast:: ge => v > min,
447
- ast:: eq | ast:: ne => v >= min && v <= max,
448
- _ => fail
449
- }
450
- }
451
-
452
- pure fn rev_binop( binop: ast:: binop) -> ast:: binop {
453
- match binop {
454
- ast:: lt => ast:: ge,
455
- ast:: le => ast:: gt,
456
- ast:: gt => ast:: le,
457
- ast:: ge => ast:: lt,
458
- _ => binop
459
- }
460
- }
461
-
462
- fn check_limits( cx: ty:: ctxt, binop: ast:: binop, l: & ast:: expr,
463
- r: & ast:: expr) -> bool {
464
- let ( lit, expr, swap) = match ( l. node, r. node) {
465
- ( ast:: expr_lit( _) , _) => ( l, r, true) ,
466
- ( _, ast:: expr_lit( _) ) => ( r, l, false) ,
467
- _ => return true
468
- } ;
469
- // Normalize the binop so that the literal is always on the RHS in
470
- // the comparison
471
- let norm_binop = if ( swap) {
472
- rev_binop( binop)
473
- } else {
474
- binop
475
- } ;
476
- match ty:: get( ty:: expr_ty( cx, @* expr) ) . sty {
477
- ty:: ty_int( int_ty) => {
478
- let ( min, max) : ( i64 , i64 ) = match int_ty {
479
- ast:: ty_i => ( int:: min_value as i64 , int:: max_value as i64 ) ,
480
- ast:: ty_char => ( u32 :: min_value as i64 , u32 :: max_value as i64 ) ,
481
- ast:: ty_i8 => ( i8 :: min_value as i64 , i8 :: max_value as i64 ) ,
482
- ast:: ty_i16 => ( i16 :: min_value as i64 , i16 :: max_value as i64 ) ,
483
- ast:: ty_i32 => ( i32 :: min_value as i64 , i32 :: max_value as i64 ) ,
484
- ast:: ty_i64 => ( i64 :: min_value, i64 :: max_value)
485
- } ;
486
- let lit_val: i64 = match lit. node {
487
- ast:: expr_lit( @li) => match li. node {
488
- ast:: lit_int( v, _) => v,
489
- ast:: lit_uint( v, _) => v as i64 ,
490
- ast:: lit_int_unsuffixed( v) => v,
491
- _ => return true
492
- } ,
493
- _ => fail
494
- } ;
495
- is_valid( norm_binop, lit_val, min, max)
496
- }
497
- ty:: ty_uint( uint_ty) => {
498
- let ( min, max) : ( u64 , u64 ) = match uint_ty {
499
- ast:: ty_u => ( uint:: min_value as u64 , uint:: max_value as u64 ) ,
500
- ast:: ty_u8 => ( u8 :: min_value as u64 , u8 :: max_value as u64 ) ,
501
- ast:: ty_u16 => ( u16 :: min_value as u64 , u16 :: max_value as u64 ) ,
502
- ast:: ty_u32 => ( u32 :: min_value as u64 , u32 :: max_value as u64 ) ,
503
- ast:: ty_u64 => ( u64 :: min_value, u64 :: max_value)
504
- } ;
505
- let lit_val: u64 = match lit. node {
506
- ast:: expr_lit( @li) => match li. node {
507
- ast:: lit_int( v, _) => v as u64 ,
508
- ast:: lit_uint( v, _) => v,
509
- ast:: lit_int_unsuffixed( v) => v as u64 ,
510
- _ => return true
511
- } ,
512
- _ => fail
513
- } ;
514
- is_valid( norm_binop, lit_val, min, max)
515
- }
516
- _ => true
517
- }
518
- }
519
-
520
- let visit = item_stopping_visitor( visit:: mk_simple_visitor( @{
521
- visit_expr: fn @( e: @ast:: expr) {
522
- match e. node {
523
- ast:: expr_binary( binop, @l, @r) => {
524
- match binop {
525
- ast:: eq | ast:: lt | ast:: le | ast:: ne | ast:: ge | ast:: gt => {
526
- if !check_limits( cx, binop, & l, & r) {
527
- cx. sess. span_lint( type_limits, e. id, it. id, e. span,
528
- ~"comparison is useless due to type limits") ;
529
- }
530
- }
531
- _ => ( )
532
- }
533
- }
534
- _ => ( )
535
- }
536
- } ,
537
- .. * visit:: default_simple_visitor( )
538
- } ) ) ;
539
- visit:: visit_item( it, ( ) , visit) ;
441
+ pure fn is_valid<T : cmp:: Ord >( binop: ast:: binop, v: T ,
442
+ min: T , max: T ) -> bool {
443
+ match binop {
444
+ ast:: lt => v <= max,
445
+ ast:: le => v < max,
446
+ ast:: gt => v >= min,
447
+ ast:: ge => v > min,
448
+ ast:: eq | ast:: ne => v >= min && v <= max,
449
+ _ => fail
450
+ }
451
+ }
452
+
453
+ pure fn rev_binop( binop: ast:: binop) -> ast:: binop {
454
+ match binop {
455
+ ast:: lt => ast:: gt,
456
+ ast:: le => ast:: ge,
457
+ ast:: gt => ast:: lt,
458
+ ast:: ge => ast:: le,
459
+ _ => binop
460
+ }
461
+ }
462
+
463
+ pure fn int_ty_range( int_ty: ast:: int_ty) -> ( i64 , i64 ) {
464
+ match int_ty {
465
+ ast:: ty_i => ( int:: min_value as i64 , int:: max_value as i64 ) ,
466
+ ast:: ty_char => ( u32 :: min_value as i64 , u32 :: max_value as i64 ) ,
467
+ ast:: ty_i8 => ( i8 :: min_value as i64 , i8 :: max_value as i64 ) ,
468
+ ast:: ty_i16 => ( i16 :: min_value as i64 , i16 :: max_value as i64 ) ,
469
+ ast:: ty_i32 => ( i32 :: min_value as i64 , i32 :: max_value as i64 ) ,
470
+ ast:: ty_i64 => ( i64 :: min_value, i64 :: max_value)
471
+ }
472
+ }
473
+
474
+ pure fn uint_ty_range( uint_ty: ast:: uint_ty) -> ( u64 , u64 ) {
475
+ match uint_ty {
476
+ ast:: ty_u => ( uint:: min_value as u64 , uint:: max_value as u64 ) ,
477
+ ast:: ty_u8 => ( u8 :: min_value as u64 , u8 :: max_value as u64 ) ,
478
+ ast:: ty_u16 => ( u16 :: min_value as u64 , u16 :: max_value as u64 ) ,
479
+ ast:: ty_u32 => ( u32 :: min_value as u64 , u32 :: max_value as u64 ) ,
480
+ ast:: ty_u64 => ( u64 :: min_value, u64 :: max_value)
481
+ }
482
+ }
483
+
484
+ fn check_limits( cx: ty:: ctxt, binop: ast:: binop, l: & ast:: expr,
485
+ r: & ast:: expr) -> bool {
486
+ let ( lit, expr, swap) = match ( l. node, r. node) {
487
+ ( ast:: expr_lit( _) , _) => ( l, r, true) ,
488
+ ( _, ast:: expr_lit( _) ) => ( r, l, false) ,
489
+ _ => return true
490
+ } ;
491
+ // Normalize the binop so that the literal is always on the RHS in
492
+ // the comparison
493
+ let norm_binop = if ( swap) {
494
+ rev_binop( binop)
495
+ } else {
496
+ binop
497
+ } ;
498
+ match ty:: get( ty:: expr_ty( cx, @* expr) ) . sty {
499
+ ty:: ty_int( int_ty) => {
500
+ let ( min, max) = int_ty_range( int_ty) ;
501
+ let lit_val: i64 = match lit. node {
502
+ ast:: expr_lit( @li) => match li. node {
503
+ ast:: lit_int( v, _) => v,
504
+ ast:: lit_uint( v, _) => v as i64 ,
505
+ ast:: lit_int_unsuffixed( v) => v,
506
+ _ => return true
507
+ } ,
508
+ _ => fail
509
+ } ;
510
+ is_valid( norm_binop, lit_val, min, max)
511
+ }
512
+ ty:: ty_uint( uint_ty) => {
513
+ let ( min, max) : ( u64 , u64 ) = uint_ty_range( uint_ty) ;
514
+ let lit_val: u64 = match lit. node {
515
+ ast:: expr_lit( @li) => match li. node {
516
+ ast:: lit_int( v, _) => v as u64 ,
517
+ ast:: lit_uint( v, _) => v,
518
+ ast:: lit_int_unsuffixed( v) => v as u64 ,
519
+ _ => return true
520
+ } ,
521
+ _ => fail
522
+ } ;
523
+ is_valid( norm_binop, lit_val, min, max)
524
+ }
525
+ _ => true
526
+ }
527
+ }
528
+
529
+ pure fn is_comparison( binop: ast:: binop) -> bool {
530
+ match binop {
531
+ ast:: eq | ast:: lt | ast:: le |
532
+ ast:: ne | ast:: ge | ast:: gt => true,
533
+ _ => false
534
+ }
535
+ }
536
+
537
+ let visit = item_stopping_visitor( visit:: mk_simple_visitor( @{
538
+ visit_expr: fn @( e: @ast:: expr) {
539
+ match e. node {
540
+ ast:: expr_binary( binop, @l, @r) => {
541
+ if is_comparison( binop)
542
+ && !check_limits( cx, binop, & l, & r) {
543
+ cx. sess. span_lint(
544
+ type_limits, e. id, it. id, e. span,
545
+ ~"comparison is useless due to type limits") ;
546
+ }
547
+ }
548
+ _ => ( )
549
+ }
550
+ } ,
551
+ .. * visit:: default_simple_visitor( )
552
+ } ) ) ;
553
+ visit:: visit_item( it, ( ) , visit) ;
540
554
}
541
555
542
556
fn check_item_structural_records( cx: ty:: ctxt, it: @ast:: item) {
0 commit comments