1
+ #![ allow( cyclomatic_complexity) ]
1
2
use rustc:: lint:: * ;
2
3
use rustc_front:: hir:: * ;
3
4
use utils:: { span_lint} ;
4
5
5
- /// **What it does:** This lint finds classic overflow checks.
6
+ /// **What it does:** This lint finds classic underflow / overflow checks.
6
7
///
7
- /// **Why is this bad?** Most classic C overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead.
8
+ /// **Why is this bad?** Most classic C underflow / overflow checks will fail in Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead.
8
9
///
9
10
/// **Known problems:** None.
10
11
///
11
12
/// **Example:** `a + b < a`
13
+
12
14
declare_lint ! ( pub OVERFLOW_CHECK_CONDITIONAL , Warn ,
13
15
"Using overflow checks which are likely to panic" ) ;
14
16
@@ -22,35 +24,50 @@ impl LintPass for OverflowCheckConditional {
22
24
}
23
25
24
26
impl LateLintPass for OverflowCheckConditional {
27
+ // a + b < a, a > a + b, a < a - b, a - b > a
25
28
fn check_expr ( & mut self , cx : & LateContext , expr : & Expr ) {
26
29
if_let_chain ! { [
27
30
let Expr_ :: ExprBinary ( ref op, ref first, ref second) = expr. node,
28
- let BinOp_ :: BiLt = op. node,
29
- let Expr_ :: ExprBinary ( ref op2, ref add1, ref add2) = first. node,
30
- let BinOp_ :: BiAdd = op2. node,
31
- let Expr_ :: ExprPath ( _, ref path1) = add1. node,
32
- let Expr_ :: ExprPath ( _, ref path2) = add2. node,
31
+ let Expr_ :: ExprBinary ( ref op2, ref ident1, ref ident2) = first. node,
32
+ let Expr_ :: ExprPath ( _, ref path1) = ident1. node,
33
+ let Expr_ :: ExprPath ( _, ref path2) = ident2. node,
33
34
let Expr_ :: ExprPath ( _, ref path3) = second. node,
34
35
( & path1. segments[ 0 ] ) . identifier == ( & path3. segments[ 0 ] ) . identifier || ( & path2. segments[ 0 ] ) . identifier == ( & path3. segments[ 0 ] ) . identifier,
35
- cx. tcx. expr_ty( add1 ) . is_integral( ) ,
36
- cx. tcx. expr_ty( add2 ) . is_integral( )
36
+ cx. tcx. expr_ty( ident1 ) . is_integral( ) ,
37
+ cx. tcx. expr_ty( ident2 ) . is_integral( )
37
38
] , {
38
- span_lint( cx, OVERFLOW_CHECK_CONDITIONAL , expr. span, "You are trying to use classic C overflow conditons that will fail in Rust." ) ;
39
+ if let BinOp_ :: BiLt = op. node {
40
+ if let BinOp_ :: BiAdd = op2. node {
41
+ span_lint( cx, OVERFLOW_CHECK_CONDITIONAL , expr. span, "You are trying to use classic C overflow conditons that will fail in Rust." ) ;
42
+ }
43
+ }
44
+ if let BinOp_ :: BiGt = op. node {
45
+ if let BinOp_ :: BiSub = op2. node {
46
+ span_lint( cx, OVERFLOW_CHECK_CONDITIONAL , expr. span, "You are trying to use classic C underflow conditons that will fail in Rust." ) ;
47
+ }
48
+ }
39
49
} }
40
50
41
51
if_let_chain ! { [
42
52
let Expr_ :: ExprBinary ( ref op, ref first, ref second) = expr. node,
43
- let BinOp_ :: BiGt = op. node,
44
- let Expr_ :: ExprBinary ( ref op2, ref sub1, ref sub2) = first. node,
45
- let BinOp_ :: BiSub = op2. node,
46
- let Expr_ :: ExprPath ( _, ref path1) = sub1. node,
47
- let Expr_ :: ExprPath ( _, ref path2) = sub2. node,
48
- let Expr_ :: ExprPath ( _, ref path3) = second. node,
53
+ let Expr_ :: ExprBinary ( ref op2, ref ident1, ref ident2) = second. node,
54
+ let Expr_ :: ExprPath ( _, ref path1) = ident1. node,
55
+ let Expr_ :: ExprPath ( _, ref path2) = ident2. node,
56
+ let Expr_ :: ExprPath ( _, ref path3) = first. node,
49
57
( & path1. segments[ 0 ] ) . identifier == ( & path3. segments[ 0 ] ) . identifier || ( & path2. segments[ 0 ] ) . identifier == ( & path3. segments[ 0 ] ) . identifier,
50
- cx. tcx. expr_ty( sub1 ) . is_integral( ) ,
51
- cx. tcx. expr_ty( sub2 ) . is_integral( )
58
+ cx. tcx. expr_ty( ident1 ) . is_integral( ) ,
59
+ cx. tcx. expr_ty( ident2 ) . is_integral( )
52
60
] , {
53
- span_lint( cx, OVERFLOW_CHECK_CONDITIONAL , expr. span, "You are trying to use classic C underflow conditons that will fail in Rust." ) ;
61
+ if let BinOp_ :: BiGt = op. node {
62
+ if let BinOp_ :: BiAdd = op2. node {
63
+ span_lint( cx, OVERFLOW_CHECK_CONDITIONAL , expr. span, "You are trying to use classic C overflow conditons that will fail in Rust." ) ;
64
+ }
65
+ }
66
+ if let BinOp_ :: BiLt = op. node {
67
+ if let BinOp_ :: BiSub = op2. node {
68
+ span_lint( cx, OVERFLOW_CHECK_CONDITIONAL , expr. span, "You are trying to use classic C underflow conditons that will fail in Rust." ) ;
69
+ }
70
+ }
54
71
} }
55
72
}
56
73
}
0 commit comments