about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-09-04 12:14:41 +0000
committerbors <bors@rust-lang.org>2019-09-04 12:14:41 +0000
commitffe57fad85ffa8561bd5ead77353337d7de23139 (patch)
treec07c345862159304e20be89b3c429854d2074080
parenta2c4b2b8da3347e9c7632592fbd978d4a97a931d (diff)
parentc6fb9c8a2a2e4a661573c49134e16f70df635860 (diff)
downloadrust-ffe57fad85ffa8561bd5ead77353337d7de23139.tar.gz
rust-ffe57fad85ffa8561bd5ead77353337d7de23139.zip
Auto merge of #4498 - sinkuu:checked_arithmetic_unwrap, r=flip1995
Add manual_saturating_arithmetic lint

changelog: add `manual_saturating_arithmetic` lint

Fixes #1557. This lint detects manual saturating arithmetics like `x.checked_add(10u32).unwrap_or(u32::max_value())` and suggests replacing with `x.saturating_add(10u32)`.
-rw-r--r--CHANGELOG.md1
-rw-r--r--README.md2
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/methods/manual_saturating_arithmetic.rs173
-rw-r--r--clippy_lints/src/methods/mod.rs34
-rw-r--r--src/lintlist/mod.rs9
-rw-r--r--tests/ui/manual_saturating_arithmetic.fixed45
-rw-r--r--tests/ui/manual_saturating_arithmetic.rs55
-rw-r--r--tests/ui/manual_saturating_arithmetic.stderr163
9 files changed, 482 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5a550e8d84f..dbdf3df4ddc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1034,6 +1034,7 @@ Released 2018-09-13
 [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
 [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
 [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
+[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
 [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
 [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
diff --git a/README.md b/README.md
index bd97910f597..dd315fd397b 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are 312 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are 313 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
 
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 4383b8b733a..a9294da59b6 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -793,6 +793,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
         methods::ITER_CLONED_COLLECT,
         methods::ITER_NTH,
         methods::ITER_SKIP_NEXT,
+        methods::MANUAL_SATURATING_ARITHMETIC,
         methods::NEW_RET_NO_SELF,
         methods::OK_EXPECT,
         methods::OPTION_AND_THEN_SOME,
@@ -958,6 +959,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
         methods::INTO_ITER_ON_REF,
         methods::ITER_CLONED_COLLECT,
         methods::ITER_SKIP_NEXT,
+        methods::MANUAL_SATURATING_ARITHMETIC,
         methods::NEW_RET_NO_SELF,
         methods::OK_EXPECT,
         methods::OPTION_MAP_OR_NONE,
diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
new file mode 100644
index 00000000000..6bfd402f7b1
--- /dev/null
+++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -0,0 +1,173 @@
+use crate::utils::{match_qpath, snippet_with_applicability, span_lint_and_sugg};
+use if_chain::if_chain;
+use rustc::hir;
+use rustc::lint::LateContext;
+use rustc_errors::Applicability;
+use rustc_target::abi::LayoutOf;
+use syntax::ast;
+
+pub fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[&[hir::Expr]], arith: &str) {
+    let unwrap_arg = &args[0][1];
+    let arith_lhs = &args[1][0];
+    let arith_rhs = &args[1][1];
+
+    let ty = cx.tables.expr_ty(arith_lhs);
+    if !ty.is_integral() {
+        return;
+    }
+
+    let mm = if let Some(mm) = is_min_or_max(cx, unwrap_arg) {
+        mm
+    } else {
+        return;
+    };
+
+    if ty.is_signed() {
+        use self::{MinMax::*, Sign::*};
+
+        let sign = if let Some(sign) = lit_sign(arith_rhs) {
+            sign
+        } else {
+            return;
+        };
+
+        match (arith, sign, mm) {
+            ("add", Pos, Max) | ("add", Neg, Min) | ("sub", Neg, Max) | ("sub", Pos, Min) => (),
+            // "mul" is omitted because lhs can be negative.
+            _ => return,
+        }
+
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            super::MANUAL_SATURATING_ARITHMETIC,
+            expr.span,
+            "manual saturating arithmetic",
+            &format!("try using `saturating_{}`", arith),
+            format!(
+                "{}.saturating_{}({})",
+                snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
+                arith,
+                snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
+            ),
+            applicability,
+        );
+    } else {
+        match (mm, arith) {
+            (MinMax::Max, "add") | (MinMax::Max, "mul") | (MinMax::Min, "sub") => (),
+            _ => return,
+        }
+
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            super::MANUAL_SATURATING_ARITHMETIC,
+            expr.span,
+            "manual saturating arithmetic",
+            &format!("try using `saturating_{}`", arith),
+            format!(
+                "{}.saturating_{}({})",
+                snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
+                arith,
+                snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
+            ),
+            applicability,
+        );
+    }
+}
+
+#[derive(PartialEq, Eq)]
+enum MinMax {
+    Min,
+    Max,
+}
+
+fn is_min_or_max<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr) -> Option<MinMax> {
+    // `T::max_value()` `T::min_value()` inherent methods
+    if_chain! {
+        if let hir::ExprKind::Call(func, args) = &expr.node;
+        if args.is_empty();
+        if let hir::ExprKind::Path(path) = &func.node;
+        if let hir::QPath::TypeRelative(_, segment) = path;
+        then {
+            match &*segment.ident.as_str() {
+                "max_value" => return Some(MinMax::Max),
+                "min_value" => return Some(MinMax::Min),
+                _ => {}
+            }
+        }
+    }
+
+    let ty = cx.tables.expr_ty(expr);
+    let ty_str = ty.to_string();
+
+    // `std::T::MAX` `std::T::MIN` constants
+    if let hir::ExprKind::Path(path) = &expr.node {
+        if match_qpath(path, &["core", &ty_str, "MAX"][..]) {
+            return Some(MinMax::Max);
+        }
+
+        if match_qpath(path, &["core", &ty_str, "MIN"][..]) {
+            return Some(MinMax::Min);
+        }
+    }
+
+    // Literals
+    let bits = cx.layout_of(ty).unwrap().size.bits();
+    let (minval, maxval): (u128, u128) = if ty.is_signed() {
+        let minval = 1 << (bits - 1);
+        let mut maxval = !(1 << (bits - 1));
+        if bits != 128 {
+            maxval &= (1 << bits) - 1;
+        }
+        (minval, maxval)
+    } else {
+        (0, if bits == 128 { !0 } else { (1 << bits) - 1 })
+    };
+
+    let check_lit = |expr: &hir::Expr, check_min: bool| {
+        if let hir::ExprKind::Lit(lit) = &expr.node {
+            if let ast::LitKind::Int(value, _) = lit.node {
+                if value == maxval {
+                    return Some(MinMax::Max);
+                }
+
+                if check_min && value == minval {
+                    return Some(MinMax::Min);
+                }
+            }
+        }
+
+        None
+    };
+
+    if let r @ Some(_) = check_lit(expr, !ty.is_signed()) {
+        return r;
+    }
+
+    if ty.is_signed() {
+        if let hir::ExprKind::Unary(hir::UnNeg, val) = &expr.node {
+            return check_lit(val, true);
+        }
+    }
+
+    None
+}
+
+#[derive(PartialEq, Eq)]
+enum Sign {
+    Pos,
+    Neg,
+}
+
+fn lit_sign(expr: &hir::Expr) -> Option<Sign> {
+    if let hir::ExprKind::Unary(hir::UnNeg, inner) = &expr.node {
+        if let hir::ExprKind::Lit(..) = &inner.node {
+            return Some(Sign::Neg);
+        }
+    } else if let hir::ExprKind::Lit(..) = &expr.node {
+        return Some(Sign::Pos);
+    }
+
+    None
+}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index f20b5c711b1..3dd12d3ff4f 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -1,3 +1,4 @@
+mod manual_saturating_arithmetic;
 mod option_map_unwrap_or;
 mod unnecessary_filter_map;
 
@@ -983,6 +984,33 @@ declare_clippy_lint! {
     "`MaybeUninit::uninit().assume_init()`"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`.
+    ///
+    /// **Why is this bad?** These can be written simply with `saturating_add/sub` methods.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// # let y: u32 = 0;
+    /// # let x: u32 = 100;
+    /// let add = x.checked_add(y).unwrap_or(u32::max_value());
+    /// let sub = x.checked_sub(y).unwrap_or(u32::min_value());
+    /// ```
+    ///
+    /// can be written using dedicated methods for saturating addition/subtraction as:
+    ///
+    /// ```rust
+    /// # let y: u32 = 0;
+    /// # let x: u32 = 100;
+    /// let add = x.saturating_add(y);
+    /// let sub = x.saturating_sub(y);
+    /// ```
+    pub MANUAL_SATURATING_ARITHMETIC,
+    style,
+    "`.chcked_add/sub(x).unwrap_or(MAX/MIN)`"
+}
+
 declare_lint_pass!(Methods => [
     OPTION_UNWRAP_USED,
     RESULT_UNWRAP_USED,
@@ -1024,6 +1052,7 @@ declare_lint_pass!(Methods => [
     INTO_ITER_ON_REF,
     SUSPICIOUS_MAP,
     UNINIT_ASSUMED_INIT,
+    MANUAL_SATURATING_ARITHMETIC,
 ]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
@@ -1076,6 +1105,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
             ["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]),
             ["count", "map"] => lint_suspicious_map(cx, expr),
             ["assume_init"] => lint_maybe_uninit(cx, &arg_lists[0][0], expr),
+            ["unwrap_or", arith @ "checked_add"]
+            | ["unwrap_or", arith @ "checked_sub"]
+            | ["unwrap_or", arith @ "checked_mul"] => {
+                manual_saturating_arithmetic::lint(cx, expr, &arg_lists, &arith["checked_".len()..])
+            },
             _ => {},
         }
 
diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs
index 8d236323825..be09ac321d2 100644
--- a/src/lintlist/mod.rs
+++ b/src/lintlist/mod.rs
@@ -6,7 +6,7 @@ pub use lint::Lint;
 pub use lint::LINT_LEVELS;
 
 // begin lint list, do not remove this comment, it’s used in `update_lints`
-pub const ALL_LINTS: [Lint; 312] = [
+pub const ALL_LINTS: [Lint; 313] = [
     Lint {
         name: "absurd_extreme_comparisons",
         group: "correctness",
@@ -932,6 +932,13 @@ pub const ALL_LINTS: [Lint; 312] = [
         module: "loops",
     },
     Lint {
+        name: "manual_saturating_arithmetic",
+        group: "style",
+        desc: "`.chcked_add/sub(x).unwrap_or(MAX/MIN)`",
+        deprecation: None,
+        module: "methods",
+    },
+    Lint {
         name: "manual_swap",
         group: "complexity",
         desc: "manual swap of two variables",
diff --git a/tests/ui/manual_saturating_arithmetic.fixed b/tests/ui/manual_saturating_arithmetic.fixed
new file mode 100644
index 00000000000..c4f53c446c9
--- /dev/null
+++ b/tests/ui/manual_saturating_arithmetic.fixed
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![allow(unused_imports)]
+
+use std::{i128, i32, u128, u32};
+
+fn main() {
+    let _ = 1u32.saturating_add(1);
+    let _ = 1u32.saturating_add(1);
+    let _ = 1u8.saturating_add(1);
+    let _ = 1u128.saturating_add(1);
+    let _ = 1u32.checked_add(1).unwrap_or(1234); // ok
+    let _ = 1u8.checked_add(1).unwrap_or(0); // ok
+    let _ = 1u32.saturating_mul(1);
+
+    let _ = 1u32.saturating_sub(1);
+    let _ = 1u32.saturating_sub(1);
+    let _ = 1u8.saturating_sub(1);
+    let _ = 1u32.checked_sub(1).unwrap_or(1234); // ok
+    let _ = 1u8.checked_sub(1).unwrap_or(255); // ok
+
+    let _ = 1i32.saturating_add(1);
+    let _ = 1i32.saturating_add(1);
+    let _ = 1i8.saturating_add(1);
+    let _ = 1i128.saturating_add(1);
+    let _ = 1i32.saturating_add(-1);
+    let _ = 1i32.saturating_add(-1);
+    let _ = 1i8.saturating_add(-1);
+    let _ = 1i128.saturating_add(-1);
+    let _ = 1i32.checked_add(1).unwrap_or(1234); // ok
+    let _ = 1i8.checked_add(1).unwrap_or(-128); // ok
+    let _ = 1i8.checked_add(-1).unwrap_or(127); // ok
+
+    let _ = 1i32.saturating_sub(1);
+    let _ = 1i32.saturating_sub(1);
+    let _ = 1i8.saturating_sub(1);
+    let _ = 1i128.saturating_sub(1);
+    let _ = 1i32.saturating_sub(-1);
+    let _ = 1i32.saturating_sub(-1);
+    let _ = 1i8.saturating_sub(-1);
+    let _ = 1i128.saturating_sub(-1);
+    let _ = 1i32.checked_sub(1).unwrap_or(1234); // ok
+    let _ = 1i8.checked_sub(1).unwrap_or(127); // ok
+    let _ = 1i8.checked_sub(-1).unwrap_or(-128); // ok
+}
diff --git a/tests/ui/manual_saturating_arithmetic.rs b/tests/ui/manual_saturating_arithmetic.rs
new file mode 100644
index 00000000000..cd83cf6e65e
--- /dev/null
+++ b/tests/ui/manual_saturating_arithmetic.rs
@@ -0,0 +1,55 @@
+// run-rustfix
+
+#![allow(unused_imports)]
+
+use std::{i128, i32, u128, u32};
+
+fn main() {
+    let _ = 1u32.checked_add(1).unwrap_or(u32::max_value());
+    let _ = 1u32.checked_add(1).unwrap_or(u32::MAX);
+    let _ = 1u8.checked_add(1).unwrap_or(255);
+    let _ = 1u128
+        .checked_add(1)
+        .unwrap_or(340_282_366_920_938_463_463_374_607_431_768_211_455);
+    let _ = 1u32.checked_add(1).unwrap_or(1234); // ok
+    let _ = 1u8.checked_add(1).unwrap_or(0); // ok
+    let _ = 1u32.checked_mul(1).unwrap_or(u32::MAX);
+
+    let _ = 1u32.checked_sub(1).unwrap_or(u32::min_value());
+    let _ = 1u32.checked_sub(1).unwrap_or(u32::MIN);
+    let _ = 1u8.checked_sub(1).unwrap_or(0);
+    let _ = 1u32.checked_sub(1).unwrap_or(1234); // ok
+    let _ = 1u8.checked_sub(1).unwrap_or(255); // ok
+
+    let _ = 1i32.checked_add(1).unwrap_or(i32::max_value());
+    let _ = 1i32.checked_add(1).unwrap_or(i32::MAX);
+    let _ = 1i8.checked_add(1).unwrap_or(127);
+    let _ = 1i128
+        .checked_add(1)
+        .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727);
+    let _ = 1i32.checked_add(-1).unwrap_or(i32::min_value());
+    let _ = 1i32.checked_add(-1).unwrap_or(i32::MIN);
+    let _ = 1i8.checked_add(-1).unwrap_or(-128);
+    let _ = 1i128
+        .checked_add(-1)
+        .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728);
+    let _ = 1i32.checked_add(1).unwrap_or(1234); // ok
+    let _ = 1i8.checked_add(1).unwrap_or(-128); // ok
+    let _ = 1i8.checked_add(-1).unwrap_or(127); // ok
+
+    let _ = 1i32.checked_sub(1).unwrap_or(i32::min_value());
+    let _ = 1i32.checked_sub(1).unwrap_or(i32::MIN);
+    let _ = 1i8.checked_sub(1).unwrap_or(-128);
+    let _ = 1i128
+        .checked_sub(1)
+        .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728);
+    let _ = 1i32.checked_sub(-1).unwrap_or(i32::max_value());
+    let _ = 1i32.checked_sub(-1).unwrap_or(i32::MAX);
+    let _ = 1i8.checked_sub(-1).unwrap_or(127);
+    let _ = 1i128
+        .checked_sub(-1)
+        .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727);
+    let _ = 1i32.checked_sub(1).unwrap_or(1234); // ok
+    let _ = 1i8.checked_sub(1).unwrap_or(127); // ok
+    let _ = 1i8.checked_sub(-1).unwrap_or(-128); // ok
+}
diff --git a/tests/ui/manual_saturating_arithmetic.stderr b/tests/ui/manual_saturating_arithmetic.stderr
new file mode 100644
index 00000000000..d985f2e754b
--- /dev/null
+++ b/tests/ui/manual_saturating_arithmetic.stderr
@@ -0,0 +1,163 @@
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:8:13
+   |
+LL |     let _ = 1u32.checked_add(1).unwrap_or(u32::max_value());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u32.saturating_add(1)`
+   |
+   = note: `-D clippy::manual-saturating-arithmetic` implied by `-D warnings`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:9:13
+   |
+LL |     let _ = 1u32.checked_add(1).unwrap_or(u32::MAX);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u32.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:10:13
+   |
+LL |     let _ = 1u8.checked_add(1).unwrap_or(255);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u8.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:11:13
+   |
+LL |       let _ = 1u128
+   |  _____________^
+LL | |         .checked_add(1)
+LL | |         .unwrap_or(340_282_366_920_938_463_463_374_607_431_768_211_455);
+   | |_______________________________________________________________________^ help: try using `saturating_add`: `1u128.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:16:13
+   |
+LL |     let _ = 1u32.checked_mul(1).unwrap_or(u32::MAX);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_mul`: `1u32.saturating_mul(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:18:13
+   |
+LL |     let _ = 1u32.checked_sub(1).unwrap_or(u32::min_value());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u32.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:19:13
+   |
+LL |     let _ = 1u32.checked_sub(1).unwrap_or(u32::MIN);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u32.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:20:13
+   |
+LL |     let _ = 1u8.checked_sub(1).unwrap_or(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u8.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:24:13
+   |
+LL |     let _ = 1i32.checked_add(1).unwrap_or(i32::max_value());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:25:13
+   |
+LL |     let _ = 1i32.checked_add(1).unwrap_or(i32::MAX);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:26:13
+   |
+LL |     let _ = 1i8.checked_add(1).unwrap_or(127);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i8.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:27:13
+   |
+LL |       let _ = 1i128
+   |  _____________^
+LL | |         .checked_add(1)
+LL | |         .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727);
+   | |_______________________________________________________________________^ help: try using `saturating_add`: `1i128.saturating_add(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:30:13
+   |
+LL |     let _ = 1i32.checked_add(-1).unwrap_or(i32::min_value());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:31:13
+   |
+LL |     let _ = 1i32.checked_add(-1).unwrap_or(i32::MIN);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:32:13
+   |
+LL |     let _ = 1i8.checked_add(-1).unwrap_or(-128);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i8.saturating_add(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:33:13
+   |
+LL |       let _ = 1i128
+   |  _____________^
+LL | |         .checked_add(-1)
+LL | |         .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728);
+   | |________________________________________________________________________^ help: try using `saturating_add`: `1i128.saturating_add(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:40:13
+   |
+LL |     let _ = 1i32.checked_sub(1).unwrap_or(i32::min_value());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:41:13
+   |
+LL |     let _ = 1i32.checked_sub(1).unwrap_or(i32::MIN);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:42:13
+   |
+LL |     let _ = 1i8.checked_sub(1).unwrap_or(-128);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i8.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:43:13
+   |
+LL |       let _ = 1i128
+   |  _____________^
+LL | |         .checked_sub(1)
+LL | |         .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728);
+   | |________________________________________________________________________^ help: try using `saturating_sub`: `1i128.saturating_sub(1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:46:13
+   |
+LL |     let _ = 1i32.checked_sub(-1).unwrap_or(i32::max_value());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:47:13
+   |
+LL |     let _ = 1i32.checked_sub(-1).unwrap_or(i32::MAX);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:48:13
+   |
+LL |     let _ = 1i8.checked_sub(-1).unwrap_or(127);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i8.saturating_sub(-1)`
+
+error: manual saturating arithmetic
+  --> $DIR/manual_saturating_arithmetic.rs:49:13
+   |
+LL |       let _ = 1i128
+   |  _____________^
+LL | |         .checked_sub(-1)
+LL | |         .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727);
+   | |_______________________________________________________________________^ help: try using `saturating_sub`: `1i128.saturating_sub(-1)`
+
+error: aborting due to 24 previous errors
+