5 /// **What it does:** Detects classic underflow/overflow checks.
7 /// **Why is this bad?** Most classic C underflow/overflow checks will fail in
8 /// Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead.
10 /// **Known problems:** None.
17 pub OVERFLOW_CHECK_CONDITIONAL
,
19 "overflow checks inspired by C which are likely to panic"
22 #[derive(Copy, Clone)]
23 pub struct OverflowCheckConditional
;
25 impl LintPass
for OverflowCheckConditional
{
26 fn get_lints(&self) -> LintArray
{
27 lint_array
!(OVERFLOW_CHECK_CONDITIONAL
)
31 impl<'a
, 'tcx
> LateLintPass
<'a
, 'tcx
> for OverflowCheckConditional
{
32 // a + b < a, a > a + b, a < a - b, a - b > a
33 fn check_expr(&mut self, cx
: &LateContext
<'a
, 'tcx
>, expr
: &'tcx Expr
) {
35 if let Expr_
::ExprBinary(ref op
, ref first
, ref second
) = expr
.node
;
36 if let Expr_
::ExprBinary(ref op2
, ref ident1
, ref ident2
) = first
.node
;
37 if let Expr_
::ExprPath(QPath
::Resolved(_
, ref path1
)) = ident1
.node
;
38 if let Expr_
::ExprPath(QPath
::Resolved(_
, ref path2
)) = ident2
.node
;
39 if let Expr_
::ExprPath(QPath
::Resolved(_
, ref path3
)) = second
.node
;
40 if path1
.segments
[0] == path3
.segments
[0] || path2
.segments
[0] == path3
.segments
[0];
41 if cx
.tables
.expr_ty(ident1
).is_integral();
42 if cx
.tables
.expr_ty(ident2
).is_integral();
44 if let BinOp_
::BiLt
= op
.node
{
45 if let BinOp_
::BiAdd
= op2
.node
{
46 span_lint(cx
, OVERFLOW_CHECK_CONDITIONAL
, expr
.span
,
47 "You are trying to use classic C overflow conditions that will fail in Rust.");
50 if let BinOp_
::BiGt
= op
.node
{
51 if let BinOp_
::BiSub
= op2
.node
{
52 span_lint(cx
, OVERFLOW_CHECK_CONDITIONAL
, expr
.span
,
53 "You are trying to use classic C underflow conditions that will fail in Rust.");
60 if let Expr_
::ExprBinary(ref op
, ref first
, ref second
) = expr
.node
;
61 if let Expr_
::ExprBinary(ref op2
, ref ident1
, ref ident2
) = second
.node
;
62 if let Expr_
::ExprPath(QPath
::Resolved(_
, ref path1
)) = ident1
.node
;
63 if let Expr_
::ExprPath(QPath
::Resolved(_
, ref path2
)) = ident2
.node
;
64 if let Expr_
::ExprPath(QPath
::Resolved(_
, ref path3
)) = first
.node
;
65 if path1
.segments
[0] == path3
.segments
[0] || path2
.segments
[0] == path3
.segments
[0];
66 if cx
.tables
.expr_ty(ident1
).is_integral();
67 if cx
.tables
.expr_ty(ident2
).is_integral();
69 if let BinOp_
::BiGt
= op
.node
{
70 if let BinOp_
::BiAdd
= op2
.node
{
71 span_lint(cx
, OVERFLOW_CHECK_CONDITIONAL
, expr
.span
,
72 "You are trying to use classic C overflow conditions that will fail in Rust.");
75 if let BinOp_
::BiLt
= op
.node
{
76 if let BinOp_
::BiSub
= op2
.node
{
77 span_lint(cx
, OVERFLOW_CHECK_CONDITIONAL
, expr
.span
,
78 "You are trying to use classic C underflow conditions that will fail in Rust.");