@@ -65,6 +65,7 @@ enum lint {
65
65
non_camel_case_types,
66
66
structural_records,
67
67
type_limits,
68
+ type_overflow,
68
69
default_methods,
69
70
deprecated_self,
70
71
@@ -204,6 +205,11 @@ fn get_lint_dict() -> lint_dict {
204
205
desc: ~"comparisons made useless by limits of the types involved",
205
206
default : warn} ) ,
206
207
208
+ ( ~"type_overflow",
209
+ @{ lint: type_overflow,
210
+ desc: ~"the integer overflowed the container type ",
211
+ default : warn} ) ,
212
+
207
213
( ~"default_methods",
208
214
@{ lint: default_methods,
209
215
desc: ~"allow default methods",
@@ -474,6 +480,10 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
474
480
}
475
481
}
476
482
483
+ pure fn is_valid_always<T : cmp:: Ord >( v: T , min: T , max: T ) -> bool {
484
+ v <= max && v >= min
485
+ }
486
+
477
487
pure fn rev_binop( binop: ast:: binop) -> ast:: binop {
478
488
match binop {
479
489
ast:: lt => ast:: gt,
@@ -505,7 +515,7 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
505
515
}
506
516
}
507
517
508
- fn check_limits( cx: ty:: ctxt, binop: ast:: binop, l: & ast:: expr,
518
+ fn check_limits( cx: ty:: ctxt, binop: Option < ast:: binop> , l: & ast:: expr,
509
519
r: & ast:: expr) -> bool {
510
520
let ( lit, expr, swap) = match ( l. node, r. node) {
511
521
( ast:: expr_lit( _) , _) => ( l, r, true) ,
@@ -514,10 +524,12 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
514
524
} ;
515
525
// Normalize the binop so that the literal is always on the RHS in
516
526
// the comparison
517
- let norm_binop = if ( swap) {
518
- rev_binop( binop)
519
- } else {
520
- binop
527
+ let norm_binop = |binop: ast:: binop| {
528
+ if ( swap) {
529
+ rev_binop( binop)
530
+ } else {
531
+ binop
532
+ }
521
533
} ;
522
534
match ty:: get( ty:: expr_ty( cx, @* expr) ) . sty {
523
535
ty:: ty_int( int_ty) => {
@@ -531,7 +543,14 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
531
543
} ,
532
544
_ => fail
533
545
} ;
534
- is_valid( norm_binop, lit_val, min, max)
546
+ match binop {
547
+ Some ( binop_) => {
548
+ is_valid( norm_binop( binop_) , lit_val, min, max)
549
+ }
550
+ None => {
551
+ is_valid_always( lit_val, min, max)
552
+ }
553
+ }
535
554
}
536
555
ty:: ty_uint( uint_ty) => {
537
556
let ( min, max) : ( u64 , u64 ) = uint_ty_range( uint_ty) ;
@@ -544,7 +563,14 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
544
563
} ,
545
564
_ => fail
546
565
} ;
547
- is_valid( norm_binop, lit_val, min, max)
566
+ match binop {
567
+ Some ( binop_) => {
568
+ is_valid( norm_binop( binop_) , lit_val, min, max)
569
+ }
570
+ None => {
571
+ is_valid_always( lit_val, min, max)
572
+ }
573
+ }
548
574
}
549
575
_ => true
550
576
}
@@ -563,12 +589,20 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
563
589
match e. node {
564
590
ast:: expr_binary( ref binop, @ref l, @ref r) => {
565
591
if is_comparison( * binop)
566
- && !check_limits( cx, * binop, l, r) {
592
+ && !check_limits( cx, Some ( * binop) , l, r) {
567
593
cx. sess. span_lint(
568
594
type_limits, e. id, it. id, e. span,
569
595
~"comparison is useless due to type limits") ;
570
596
}
571
597
}
598
+ ast:: expr_assign( @ref l, @ref r) |
599
+ ast:: expr_assign_op( _ , @ref l, @ref r) => {
600
+ if !check_limits( cx, None , l, r) {
601
+ cx. sess. span_lint(
602
+ type_limits, e. id, it. id, e. span,
603
+ ~"the integer overflowed the container type ") ;
604
+ }
605
+ }
572
606
_ => ( )
573
607
}
574
608
} ,
0 commit comments