diff --git a/CHANGELOG.md b/CHANGELOG.md index 5448b1267be6..3411a024ba37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5159,6 +5159,7 @@ Released 2018-09-13 [`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits +[`manual_checked_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_checked_op [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 85854a0dfb76..822bedfa59dd 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -283,6 +283,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_assert::MANUAL_ASSERT_INFO, crate::manual_async_fn::MANUAL_ASYNC_FN_INFO, crate::manual_bits::MANUAL_BITS_INFO, + crate::manual_checked_op::MANUAL_CHECKED_OP_INFO, crate::manual_clamp::MANUAL_CLAMP_INFO, crate::manual_float_methods::MANUAL_IS_FINITE_INFO, crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c462c9330825..dab554fd4049 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -185,6 +185,7 @@ mod main_recursion; mod manual_assert; mod manual_async_fn; mod manual_bits; +mod manual_checked_op; mod manual_clamp; mod manual_float_methods; mod manual_hash_one; @@ -1066,6 +1067,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv()))); store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter)); store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType)); + store.register_late_pass(|_| Box::new(manual_checked_op::ManualCheckedOp)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_checked_op.rs b/clippy_lints/src/manual_checked_op.rs new file mode 100644 index 000000000000..09b995f0cbce --- /dev/null +++ b/clippy_lints/src/manual_checked_op.rs @@ -0,0 +1,540 @@ +use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::macros::PanicExpn; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::{ + can_move_expr_to_closure, is_else_clause, is_from_proc_macro, is_never_expr, is_res_lang_ctor, path_res, + peel_blocks, RequiresSemi, SpanlessEq, +}; +use core::mem; +use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, QPath}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, Ty, TypeckResults}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of `checked_*` integer functions. + /// + /// ### Why is this bad? + /// A call to one of the `checked_*` is clearer. + /// + /// ### Example + /// ```no_run + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```no_run + /// // example code which does not raise clippy warning + /// ``` + #[clippy::version = "1.75.0"] + pub MANUAL_CHECKED_OP, + complexity, + "manual implementation of a checked operator" +} + +declare_lint_pass!(ManualCheckedOp => [MANUAL_CHECKED_OP]); + +impl<'tcx> LateLintPass<'tcx> for ManualCheckedOp { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { + if let Some((cond, then, else_kind, else_)) = parse_branch_exprs(cx, e) + && let (is_option, then) = try_unwrap_some(cx, then) + && let ExprKind::Binary(op, lhs, rhs) = then.kind + && let typeck = cx.typeck_results() + && let ty = typeck.expr_ty(lhs) + && let Some(int_ty) = IntTy::from_ty(ty) + && let ctxt = e.span.ctxt() + && then.span.ctxt() == ctxt + && let (method, lhs, rhs) = match op.node { + BinOpKind::Shl if is_checked_shift(cx, typeck, int_ty, &cond, rhs) => ("checked_shl", lhs, rhs), + BinOpKind::Shr if is_checked_shift(cx, typeck, int_ty, &cond, rhs) => ("checked_shr", lhs, rhs), + BinOpKind::Div if int_ty.is_unsigned() && is_checked_div(cx, typeck, &cond, rhs) => { + ("checked_div", lhs, rhs) + }, + BinOpKind::Rem if int_ty.is_unsigned() && is_checked_div(cx, typeck, &cond, rhs) => { + ("checked_rem", lhs, rhs) + }, + BinOpKind::Sub if is_checked_sub(cx, typeck, int_ty, &cond, lhs, rhs) => ("checked_sub", lhs, rhs), + BinOpKind::Add if let Some((lhs, rhs)) = is_checked_add(cx, typeck, int_ty, &cond, lhs, rhs) => { + ("checked_add", lhs, rhs) + }, + _ => return, + } + && !in_external_macro(cx.sess(), e.span) + && !is_from_proc_macro(cx, e) + { + span_lint_and_then( + cx, + MANUAL_CHECKED_OP, + e.span, + &format!("manual implementation of `{method}`"), + |diag| { + let mut app = Applicability::MachineApplicable; + let lhs_snip = snippet_with_context(cx, lhs.span, ctxt, "..", &mut app).0; + let rhs_snip = snippet_with_context(cx, rhs.span, ctxt, "..", &mut app).0; + let sugg = if is_option && matches!(else_kind, ElseKind::None) { + format!("{lhs_snip}.{method}({rhs_snip})") + } else { + let panic_kind = if !is_option && let Some(expn) = PanicExpn::parse_at_ctxt(cx, else_, ctxt) { + match expn { + PanicExpn::Empty => Some(None), + PanicExpn::Str(msg) => Some(Some(msg)), + _ => None, + } + } else { + None + }; + match panic_kind { + Some(None) => format!("{lhs_snip}.{method}({rhs_snip}).unwrap()"), + Some(Some(msg)) => { + let msg_snip = snippet_with_applicability(cx, msg.span, "..", &mut app); + format!("{lhs_snip}.{method}({rhs_snip}).expect({msg_snip})") + }, + None => { + assert!(can_move_expr_to_closure(cx, else_).is_some()); + let else_snip = snippet_with_context(cx, else_.span, ctxt, "..", &mut app).0; + if is_option { + format!("{lhs_snip}.{method}({rhs_snip}).or_else(|| {else_snip})") + } else { + format!("{lhs_snip}.{method}({rhs_snip}).unwrap_or_else(|| {else_snip})") + } + }, + } + }; + let sugg = if is_else_clause(cx.tcx, e) { + format!("else {{ {sugg} }}") + } else { + sugg + }; + diag.span_suggestion(e.span, "try", sugg, app); + }, + ); + } + } +} + +#[derive(Clone, Copy)] +enum IntTy { + Int(ty::IntTy), + Uint(ty::UintTy), +} +impl PartialEq> for IntTy { + fn eq(&self, other: &Ty<'_>) -> bool { + match (self, other.kind()) { + (Self::Int(x), ty::Int(y)) => x == y, + (Self::Uint(x), ty::Uint(y)) => x == y, + _ => false, + } + } +} +impl IntTy { + fn from_ty(ty: Ty<'_>) -> Option { + match *ty.kind() { + ty::Int(ty) => Some(Self::Int(ty)), + ty::Uint(ty) => Some(Self::Uint(ty)), + _ => None, + } + } + + fn name_sym(self) -> Symbol { + match self { + Self::Int(ty::IntTy::I8) => sym::i8, + Self::Int(ty::IntTy::I16) => sym::i16, + Self::Int(ty::IntTy::I32) => sym::i32, + Self::Int(ty::IntTy::I64) => sym::i64, + Self::Int(ty::IntTy::I128) => sym::i128, + Self::Int(ty::IntTy::Isize) => sym::isize, + Self::Uint(ty::UintTy::U8) => sym::u8, + Self::Uint(ty::UintTy::U16) => sym::u16, + Self::Uint(ty::UintTy::U32) => sym::u32, + Self::Uint(ty::UintTy::U64) => sym::u64, + Self::Uint(ty::UintTy::U128) => sym::u128, + Self::Uint(ty::UintTy::Usize) => sym::usize, + } + } + + fn bits(self) -> Option { + match self { + Self::Int(ty::IntTy::I8) => Some(8), + Self::Int(ty::IntTy::I16) => Some(16), + Self::Int(ty::IntTy::I32) => Some(32), + Self::Int(ty::IntTy::I64) => Some(64), + Self::Int(ty::IntTy::I128) => Some(128), + Self::Uint(ty::UintTy::U8) => Some(8), + Self::Uint(ty::UintTy::U16) => Some(16), + Self::Uint(ty::UintTy::U32) => Some(32), + Self::Uint(ty::UintTy::U64) => Some(64), + Self::Uint(ty::UintTy::U128) => Some(128), + _ => None, + } + } + + fn min(self) -> Option { + match self { + Self::Int(ty::IntTy::I8) => Some(i8::MIN.into()), + Self::Int(ty::IntTy::I16) => Some(i16::MIN.into()), + Self::Int(ty::IntTy::I32) => Some(i32::MIN.into()), + Self::Int(ty::IntTy::I64) => Some(i64::MIN.into()), + Self::Int(ty::IntTy::I128) => Some(i128::MIN), + Self::Int(ty::IntTy::Isize) => None, + Self::Uint(_) => Some(0), + } + } + + fn max(self) -> Option { + match self { + Self::Int(ty::IntTy::I8) => Some(i8::MAX as u128), + Self::Int(ty::IntTy::I16) => Some(i16::MAX as u128), + Self::Int(ty::IntTy::I32) => Some(i32::MAX as u128), + Self::Int(ty::IntTy::I64) => Some(i64::MAX as u128), + Self::Int(ty::IntTy::I128) => Some(i128::MAX as u128), + Self::Uint(ty::UintTy::U8) => Some(u8::MAX.into()), + Self::Uint(ty::UintTy::U16) => Some(u16::MAX.into()), + Self::Uint(ty::UintTy::U32) => Some(u32::MAX.into()), + Self::Uint(ty::UintTy::U64) => Some(u64::MAX.into()), + Self::Uint(ty::UintTy::U128) => Some(u128::MAX), + _ => None, + } + } + + fn is_unsigned(self) -> bool { + matches!(self, Self::Uint(_)) + } +} + +fn is_checked_shift<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + int_ty: IntTy, + cond: &CmpOp<'tcx>, + shift_by: &'tcx Expr<'_>, +) -> bool { + match ConstIntOp::from_expr(cx, typeck, int_ty, cond.rhs) { + Some(ConstIntOp::Const(c)) => match cond.op { + OpKind::Lt if Some(c) == int_ty.bits().map(u128::from) => {}, + OpKind::Le if Some(c) == int_ty.bits().map(|x| u128::from(x - 1)) => {}, + _ => return false, + }, + Some(ConstIntOp::IntConst(IntConst::Bits)) if matches!(cond.op, OpKind::Lt) => {}, + Some(ConstIntOp::Sub(IntConst::Bits, 1)) if matches!(cond.op, OpKind::Le) => {}, + _ => return false, + }; + SpanlessEq::new(cx).eq_expr(cond.lhs, shift_by) +} + +fn is_checked_div<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + cond: &CmpOp<'tcx>, + divisor: &'tcx Expr<'_>, +) -> bool { + if !matches!(cond.op, OpKind::Ne) { + return false; + } + let (const_, other) = if let Some(x) = constant_simple(cx, typeck, cond.lhs) { + (x, cond.rhs) + } else if let Some(x) = constant_simple(cx, typeck, cond.rhs) { + (x, cond.lhs) + } else { + return false; + }; + matches!(const_, Constant::Int(0)) && SpanlessEq::new(cx).eq_expr(other, divisor) +} + +fn is_checked_sub<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + int_ty: IntTy, + cond: &CmpOp<'tcx>, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, +) -> bool { + if !matches!(cond.op, OpKind::Lt) { + return false; + } + let limit_eq = if let Some(Constant::Int(rhs_const)) = constant_simple(cx, typeck, rhs) + && let Some(Constant::Int(cond_const)) = constant_simple(cx, typeck, cond.rhs) + { + if int_ty.is_unsigned() { + rhs_const == cond_const + } else if rhs_const as i128 > 0 + && let Some(min) = int_ty.min() + { + rhs_const as i128 + min == cond_const as i128 + } else { + return false; + } + } else if int_ty.is_unsigned() { + SpanlessEq::new(cx).eq_expr(cond.rhs, rhs) + } else { + return false; + }; + limit_eq && SpanlessEq::new(cx).eq_expr(cond.lhs, lhs) +} + +fn is_checked_add<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + int_ty: IntTy, + cond: &CmpOp<'tcx>, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, +) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { + let (lhs, rhs, op_const) = if let Some(op_const) = constant_simple(cx, typeck, rhs) { + (lhs, rhs, op_const) + } else if let Some(op_const) = constant_simple(cx, typeck, lhs) { + (rhs, lhs, op_const) + } else { + return None; + }; + let Constant::Int(op_const) = op_const else { + return None; + }; + + let (cond_const, cond_other, cond_const_is_rhs) = if let Some(cond_const) = constant_simple(cx, typeck, cond.rhs) { + (cond_const, cond.lhs, true) + } else if let Some(cond_const) = constant_simple(cx, typeck, cond.lhs) { + (cond_const, cond.rhs, false) + } else { + return None; + }; + let Constant::Int(cond_const) = cond_const else { + return None; + }; + let max = int_ty.max()?; + + let limit_eq = match cond.op { + OpKind::Lt if cond_const_is_rhs && (int_ty.is_unsigned() || op_const as i128 > 0) => { + max - op_const == cond_const + }, + OpKind::Ne => max == cond_const && op_const == 1, + _ => return None, + }; + (limit_eq && SpanlessEq::new(cx).eq_expr(cond_other, lhs)).then_some((lhs, rhs)) +} + +fn parse_branch_exprs<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, +) -> Option<(CmpOp<'tcx>, &'tcx Expr<'tcx>, ElseKind, &'tcx Expr<'tcx>)> { + if let ExprKind::If(cond, then, Some(else_)) = e.kind + && let Some(mut cond) = CmpOp::parse_expr(cond.peel_drop_temps()) + { + let then = peel_blocks(then); + let else_ = peel_blocks(else_); + if let Some(else_kind) = ElseKind::parse_expr(cx, else_) { + Some((cond, then, else_kind, else_)) + } else if let Some(else_kind) = ElseKind::parse_expr(cx, then) { + cond.inv(); + Some((cond, else_, else_kind, then)) + } else { + None + } + } else { + None + } +} + +enum ElseKind { + None, + Diverge(RequiresSemi), +} +impl ElseKind { + fn parse_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option { + if let Some(semi) = is_never_expr(cx, e) { + Some(Self::Diverge(semi)) + } else if is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionNone) { + Some(Self::None) + } else { + None + } + } +} + +#[derive(Clone, Copy)] +enum OpKind { + Eq, + Ne, + Lt, + Le, +} +pub struct CmpOp<'tcx> { + op: OpKind, + lhs: &'tcx Expr<'tcx>, + rhs: &'tcx Expr<'tcx>, +} +impl<'tcx> CmpOp<'tcx> { + fn parse_expr(e: &'tcx Expr<'_>) -> Option { + if let ExprKind::Binary(op, lhs, rhs) = e.kind { + match op.node { + BinOpKind::Eq => Some(Self { + op: OpKind::Eq, + lhs, + rhs, + }), + BinOpKind::Ne => Some(Self { + op: OpKind::Ne, + lhs, + rhs, + }), + BinOpKind::Lt => Some(Self { + op: OpKind::Lt, + lhs, + rhs, + }), + BinOpKind::Le => Some(Self { + op: OpKind::Le, + lhs, + rhs, + }), + BinOpKind::Gt => Some(Self { + op: OpKind::Lt, + lhs: rhs, + rhs: lhs, + }), + BinOpKind::Ge => Some(Self { + op: OpKind::Le, + lhs: rhs, + rhs: lhs, + }), + _ => None, + } + } else { + None + } + } + + fn inv(&mut self) { + match self.op { + OpKind::Eq => self.op = OpKind::Ne, + OpKind::Ne => self.op = OpKind::Eq, + OpKind::Lt => { + self.op = OpKind::Le; + mem::swap(&mut self.lhs, &mut self.rhs); + }, + OpKind::Le => { + self.op = OpKind::Lt; + mem::swap(&mut self.lhs, &mut self.rhs); + }, + } + } +} + +#[derive(Clone, Copy)] +enum IntConst { + Bits, + Min, + Max, +} +impl IntConst { + fn from_path<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + ty: IntTy, + p: &'tcx QPath<'_>, + ) -> Option { + match p { + QPath::Resolved(None, path) + if let Res::Def(DefKind::Const, did) = path.res + && let path = cx.get_def_path(did) + && let &[sym::core, ty_name, item_name] = &*path + && ty_name == ty.name_sym() => + { + match item_name.as_str() { + "MIN" => Some(Self::Min), + "MAX" => Some(Self::Max), + _ => None, + } + }, + QPath::TypeRelative(path_ty, name) if typeck.node_type_opt(path_ty.hir_id).is_some_and(|x| ty == x) => { + match name.ident.as_str() { + "MIN" => Some(Self::Min), + "MAX" => Some(Self::Max), + "BITS" => Some(Self::Bits), + _ => None, + } + }, + _ => None, + } + } + + fn from_expr<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + ty: IntTy, + e: &'tcx Expr<'_>, + ) -> Option { + if let ExprKind::Path(p) = &e.kind { + Self::from_path(cx, typeck, ty, p) + } else { + None + } + } +} + +enum ConstIntOp { + Const(u128), + IntConst(IntConst), + Add(IntConst, u128), + Sub(IntConst, u128), +} +impl ConstIntOp { + fn from_expr<'tcx>( + cx: &LateContext<'tcx>, + typeck: &TypeckResults<'tcx>, + ty: IntTy, + e: &'tcx Expr<'_>, + ) -> Option { + if let Some(c) = constant_simple(cx, typeck, e) { + if let Constant::Int(c) = c { + Some(Self::Const(c)) + } else { + None + } + } else { + match e.kind { + ExprKind::Path(ref p) if let Some(c) = IntConst::from_path(cx, typeck, ty, p) => { + Some(Self::IntConst(c)) + }, + ExprKind::Binary(op, lhs, rhs) if matches!(op.node, BinOpKind::Add) => { + if let Some(lhs) = IntConst::from_expr(cx, typeck, ty, lhs) { + if let Some(Constant::Int(rhs)) = constant_simple(cx, typeck, rhs) { + Some(Self::Add(lhs, rhs)) + } else { + None + } + } else if let Some(rhs) = IntConst::from_expr(cx, typeck, ty, rhs) + && let Some(Constant::Int(lhs)) = constant_simple(cx, typeck, lhs) + { + Some(Self::Add(rhs, lhs)) + } else { + None + } + }, + ExprKind::Binary(op, lhs, rhs) + if matches!(op.node, BinOpKind::Sub) + && let Some(lhs) = IntConst::from_expr(cx, typeck, ty, lhs) + && let Some(Constant::Int(rhs)) = constant_simple(cx, typeck, rhs) => + { + Some(Self::Sub(lhs, rhs)) + }, + _ => None, + } + } + } +} + +fn try_unwrap_some<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (bool, &'tcx Expr<'tcx>) { + if let ExprKind::Call(p, [e]) = e.kind + && let res = path_res(cx, p) + && is_res_lang_ctor(cx, res, LangItem::OptionSome) + { + (true, peel_blocks(e)) + } else { + (false, e) + } +} diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 3748e2a26d19..68f427fe2640 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -10,7 +10,7 @@ use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; -use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, List, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; @@ -455,7 +455,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option> { let res = self.typeck_results.qpath_res(qpath, id); match res { - Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { + Res::Def(def_kind @ (DefKind::Const | DefKind::AssocConst), def_id) => { // Check if this constant is based on `cfg!(..)`, // which is NOT constant for our purposes. if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) @@ -486,7 +486,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .ok() .map(|val| rustc_middle::mir::Const::from_value(val, ty))?; let result = mir_to_const(self.lcx, result)?; - self.source = ConstantSource::Constant; + + if matches!(def_kind, DefKind::AssocConst) + && let impl_id = self.lcx.tcx.parent(def_id) + && matches!( + self.lcx.tcx.opt_def_kind(impl_id), + Some(DefKind::Impl { of_trait: false }) + ) + && matches!( + self.lcx.tcx.type_of(impl_id).instantiate_identity().kind(), + ty::Uint(UintTy::U8 | UintTy::U16 | UintTy::U32 | UintTy::U64 | UintTy::U128) + | ty::Int(IntTy::I8 | IntTy::I16 | IntTy::I32 | IntTy::I64 | IntTy::I128) + | ty::Char + | ty::Float(_) + ) + { + // The associated constants of these types will never change. + } else { + self.source = ConstantSource::Constant; + } Some(result) }, _ => None, diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 46ce4ffdce5d..40f7b5317ef2 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -189,6 +189,16 @@ pub fn first_node_in_macro(cx: &LateContext<'_>, node: &impl HirNode) -> Option< Some(parent_macro_call.expn) } +pub fn expn_at_ctxt(span: Span, ctxt: SyntaxContext) -> Option { + expn_backtrace(span).find_map(|(_, expn)| { + if expn.call_site.ctxt() == ctxt { + Some(expn) + } else { + None + } + }) +} + /* Specific Macro Utils */ /// Is `def_id` of `std::panic`, `core::panic` or any inner implementation macros @@ -253,7 +263,18 @@ impl<'a> PanicExpn<'a> { }; Self::Display(e) }, - "panic_fmt" => Self::Format(arg), + "panic_fmt" => { + if let ExprKind::Call(callee, [arg]) = arg.kind + && let ExprKind::Path(QPath::TypeRelative(_, path)) = callee.kind + && path.ident.as_str() == "new_const" + && let ExprKind::AddrOf(_, _, arg) = arg.kind + && let ExprKind::Array([arg]) = arg.kind + { + Self::Str(arg) + } else { + Self::Format(arg) + } + }, // Since Rust 1.52, `assert_{eq,ne}` macros expand to use: // `core::panicking::assert_failed(.., left_val, right_val, None | Some(format_args!(..)));` "assert_failed" => { @@ -273,6 +294,23 @@ impl<'a> PanicExpn<'a> { }; Some(result) } + + pub fn parse_at_ctxt(cx: &LateContext<'a>, e: &'a Expr<'_>, ctxt: SyntaxContext) -> Option { + if let Some(expn) = expn_at_ctxt(e.span, ctxt) + && let Some(did) = expn.macro_def_id + && is_panic(cx, did) + { + for_each_expr(e, |e| { + if let Some(x) = PanicExpn::parse(e) { + ControlFlow::Break(x) + } else { + ControlFlow::Continue(()) + } + }) + } else { + None + } + } } /// Finds the arguments of an `assert!` or `debug_assert!` macro call within the macro expansion diff --git a/tests/ui/const_comparisons.rs b/tests/ui/const_comparisons.rs index 0898b4ebd465..db83c63be00a 100644 --- a/tests/ui/const_comparisons.rs +++ b/tests/ui/const_comparisons.rs @@ -4,6 +4,7 @@ #![allow(clippy::no_effect)] #![allow(clippy::short_circuit_statement)] #![allow(clippy::manual_range_contains)] +#![allow(clippy::identity_op)] const STATUS_BAD_REQUEST: u16 = 400; const STATUS_SERVER_ERROR: u16 = 500; diff --git a/tests/ui/const_comparisons.stderr b/tests/ui/const_comparisons.stderr index f773ccbc711e..28c4d9b6103f 100644 --- a/tests/ui/const_comparisons.stderr +++ b/tests/ui/const_comparisons.stderr @@ -1,5 +1,5 @@ error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:45:5 + --> $DIR/const_comparisons.rs:46:5 | LL | status_code <= 400 && status_code > 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | status_code <= 400 && status_code > 500; = help: to override `-D warnings` add `#[allow(clippy::impossible_comparisons)]` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:48:5 + --> $DIR/const_comparisons.rs:49:5 | LL | status_code > 500 && status_code < 400; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | status_code > 500 && status_code < 400; = note: since `500` > `400`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:51:5 + --> $DIR/const_comparisons.rs:52:5 | LL | status_code < 500 && status_code > 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | status_code < 500 && status_code > 500; = note: `status_code` cannot simultaneously be greater than and less than `500` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:56:5 + --> $DIR/const_comparisons.rs:57:5 | LL | status_code < { 400 } && status_code > { 500 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | status_code < { 400 } && status_code > { 500 }; = note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:59:5 + --> $DIR/const_comparisons.rs:60:5 | LL | status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR; = note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:62:5 + --> $DIR/const_comparisons.rs:63:5 | LL | status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR; = note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:65:5 + --> $DIR/const_comparisons.rs:66:5 | LL | status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR; = note: `status_code` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:70:5 + --> $DIR/const_comparisons.rs:71:5 | LL | status < { 400 } && status > { 500 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | status < { 400 } && status > { 500 }; = note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:73:5 + --> $DIR/const_comparisons.rs:74:5 | LL | status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR; = note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:76:5 + --> $DIR/const_comparisons.rs:77:5 | LL | status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR; = note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:79:5 + --> $DIR/const_comparisons.rs:80:5 | LL | status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR; = note: `status` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:89:5 + --> $DIR/const_comparisons.rs:90:5 | LL | 500 >= status_code && 600 < status_code; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | 500 >= status_code && 600 < status_code; = note: since `500` < `600`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:93:5 + --> $DIR/const_comparisons.rs:94:5 | LL | 500 >= status_code && status_code > 600; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | 500 >= status_code && status_code > 600; = note: since `500` < `600`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:103:5 + --> $DIR/const_comparisons.rs:104:5 | LL | 500 >= status && 600 < status; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | 500 >= status && 600 < status; = note: since `500` < `600`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:107:5 + --> $DIR/const_comparisons.rs:108:5 | LL | 500 >= status && status > 600; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,13 +121,13 @@ LL | 500 >= status && status > 600; = note: since `500` < `600`, the expression evaluates to false for any value of `status` error: right-hand side of `&&` operator has no effect - --> $DIR/const_comparisons.rs:112:5 + --> $DIR/const_comparisons.rs:113:5 | LL | status_code < 200 && status_code <= 299; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code < 200` evaluates to true, status_code <= 299` will always evaluate to true as well - --> $DIR/const_comparisons.rs:112:23 + --> $DIR/const_comparisons.rs:113:23 | LL | status_code < 200 && status_code <= 299; | ^^^^^^^^^^^^^^^^^^^^^ @@ -135,67 +135,67 @@ LL | status_code < 200 && status_code <= 299; = help: to override `-D warnings` add `#[allow(clippy::redundant_comparisons)]` error: left-hand side of `&&` operator has no effect - --> $DIR/const_comparisons.rs:114:5 + --> $DIR/const_comparisons.rs:115:5 | LL | status_code > 200 && status_code >= 299; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code >= 299` evaluates to true, status_code > 200` will always evaluate to true as well - --> $DIR/const_comparisons.rs:114:5 + --> $DIR/const_comparisons.rs:115:5 | LL | status_code > 200 && status_code >= 299; | ^^^^^^^^^^^^^^^^^^^^^ error: left-hand side of `&&` operator has no effect - --> $DIR/const_comparisons.rs:118:5 + --> $DIR/const_comparisons.rs:119:5 | LL | status_code >= 500 && status_code > 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well - --> $DIR/const_comparisons.rs:118:5 + --> $DIR/const_comparisons.rs:119:5 | LL | status_code >= 500 && status_code > 500; | ^^^^^^^^^^^^^^^^^^^^^^ error: right-hand side of `&&` operator has no effect - --> $DIR/const_comparisons.rs:121:5 + --> $DIR/const_comparisons.rs:122:5 | LL | status_code > 500 && status_code >= 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well - --> $DIR/const_comparisons.rs:121:23 + --> $DIR/const_comparisons.rs:122:23 | LL | status_code > 500 && status_code >= 500; | ^^^^^^^^^^^^^^^^^^^^^ error: left-hand side of `&&` operator has no effect - --> $DIR/const_comparisons.rs:124:5 + --> $DIR/const_comparisons.rs:125:5 | LL | status_code <= 500 && status_code < 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well - --> $DIR/const_comparisons.rs:124:5 + --> $DIR/const_comparisons.rs:125:5 | LL | status_code <= 500 && status_code < 500; | ^^^^^^^^^^^^^^^^^^^^^^ error: right-hand side of `&&` operator has no effect - --> $DIR/const_comparisons.rs:127:5 + --> $DIR/const_comparisons.rs:128:5 | LL | status_code < 500 && status_code <= 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well - --> $DIR/const_comparisons.rs:127:23 + --> $DIR/const_comparisons.rs:128:23 | LL | status_code < 500 && status_code <= 500; | ^^^^^^^^^^^^^^^^^^^^^ error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:132:5 + --> $DIR/const_comparisons.rs:133:5 | LL | name < "Jennifer" && name > "Shannon"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +203,7 @@ LL | name < "Jennifer" && name > "Shannon"; = note: since `"Jennifer"` < `"Shannon"`, the expression evaluates to false for any value of `name` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:137:5 + --> $DIR/const_comparisons.rs:138:5 | LL | numbers < [3, 4] && numbers > [5, 6]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -211,7 +211,7 @@ LL | numbers < [3, 4] && numbers > [5, 6]; = note: since `[3, 4]` < `[5, 6]`, the expression evaluates to false for any value of `numbers` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:142:5 + --> $DIR/const_comparisons.rs:143:5 | LL | letter < 'b' && letter > 'c'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ LL | letter < 'b' && letter > 'c'; = note: since `'b'` < `'c'`, the expression evaluates to false for any value of `letter` error: boolean expression will never evaluate to 'true' - --> $DIR/const_comparisons.rs:147:5 + --> $DIR/const_comparisons.rs:148:5 | LL | area < std::f32::consts::E && area > std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_checked_op.fixed b/tests/ui/manual_checked_op.fixed new file mode 100644 index 000000000000..31559a568d3d --- /dev/null +++ b/tests/ui/manual_checked_op.fixed @@ -0,0 +1,279 @@ +#![warn(clippy::manual_checked_op)] +#![allow(clippy::int_plus_one)] + +fn main() { + // checked_shl + { + let x = 1u32; + let _ = 1u8.checked_shl(x).unwrap(); + let _ = 1u8.checked_shl(x).unwrap(); + let _ = 1u16.checked_shl(x).unwrap(); + let _ = 1u16.checked_shl(x).unwrap(); + let _ = 1u32.checked_shl(x).unwrap(); + let _ = 1u32.checked_shl(x).unwrap(); + let _ = 1u64.checked_shl(x).unwrap(); + let _ = 1u64.checked_shl(x).unwrap(); + let _ = 1u128.checked_shl(x).unwrap(); + let _ = 1u128.checked_shl(x).unwrap(); + + let _ = 1u8.checked_shl(x).unwrap(); + let _ = 1u16.checked_shl(x).unwrap(); + let _ = 1u32.checked_shl(x).unwrap(); + let _ = 1u64.checked_shl(x).unwrap(); + let _ = 1u128.checked_shl(x).unwrap(); + let _ = 1usize.checked_shl(x).unwrap(); + let _ = 1usize.checked_shl(x).unwrap(); + + let _ = 1i8.checked_shl(x).unwrap(); + let _ = 1i8.checked_shl(x).unwrap(); + let _ = 1i16.checked_shl(x).unwrap(); + let _ = 1i16.checked_shl(x).unwrap(); + let _ = 1i32.checked_shl(x).unwrap(); + let _ = 1i32.checked_shl(x).unwrap(); + let _ = 1i64.checked_shl(x).unwrap(); + let _ = 1i64.checked_shl(x).unwrap(); + let _ = 1i128.checked_shl(x).unwrap(); + let _ = 1i128.checked_shl(x).unwrap(); + + let _ = 1i8.checked_shl(x).unwrap(); + let _ = 1i16.checked_shl(x).unwrap(); + let _ = 1i32.checked_shl(x).unwrap(); + let _ = 1i64.checked_shl(x).unwrap(); + let _ = 1i128.checked_shl(x).unwrap(); + let _ = 1isize.checked_shl(x).unwrap(); + let _ = 1isize.checked_shl(x).unwrap(); + + // Off by 1 + let _ = if x < 9 { 1u8 << x } else { panic!() }; + let _ = if x <= 8 { 1u8 << x } else { panic!() }; + let _ = if x < 17 { 1u16 << x } else { panic!() }; + let _ = if x <= 16 { 1u16 << x } else { panic!() }; + let _ = if x < 33 { 1u32 << x } else { panic!() }; + let _ = if x <= 32 { 1u32 << x } else { panic!() }; + let _ = if x < 65 { 1u64 << x } else { panic!() }; + let _ = if x <= 64 { 1u64 << x } else { panic!() }; + let _ = if x < 129 { 1u128 << x } else { panic!() }; + let _ = if x <= 128 { 1u128 << x } else { panic!() }; + + let _ = if x < 9 { 1i8 << x } else { panic!() }; + let _ = if x <= 8 { 1i8 << x } else { panic!() }; + let _ = if x < 17 { 1i16 << x } else { panic!() }; + let _ = if x <= 16 { 1i16 << x } else { panic!() }; + let _ = if x < 33 { 1i32 << x } else { panic!() }; + let _ = if x <= 32 { 1i32 << x } else { panic!() }; + let _ = if x < 65 { 1i64 << x } else { panic!() }; + let _ = if x <= 64 { 1i64 << x } else { panic!() }; + let _ = if x < 129 { 1i128 << x } else { panic!() }; + let _ = if x <= 128 { 1i128 << x } else { panic!() }; + + let _ = if x < 7 { 1u8 << x } else { panic!() }; + let _ = if x <= 6 { 1u8 << x } else { panic!() }; + let _ = if x < 15 { 1u16 << x } else { panic!() }; + let _ = if x <= 14 { 1u16 << x } else { panic!() }; + let _ = if x < 31 { 1u32 << x } else { panic!() }; + let _ = if x <= 30 { 1u32 << x } else { panic!() }; + let _ = if x < 63 { 1u64 << x } else { panic!() }; + let _ = if x <= 62 { 1u64 << x } else { panic!() }; + let _ = if x < 127 { 1u128 << x } else { panic!() }; + let _ = if x <= 126 { 1u128 << x } else { panic!() }; + + let _ = if x < 7 { 1i8 << x } else { panic!() }; + let _ = if x <= 6 { 1i8 << x } else { panic!() }; + let _ = if x < 15 { 1i16 << x } else { panic!() }; + let _ = if x <= 14 { 1i16 << x } else { panic!() }; + let _ = if x < 31 { 1i32 << x } else { panic!() }; + let _ = if x <= 30 { 1i32 << x } else { panic!() }; + let _ = if x < 63 { 1i64 << x } else { panic!() }; + let _ = if x <= 62 { 1i64 << x } else { panic!() }; + let _ = if x < 127 { 1i128 << x } else { panic!() }; + let _ = if x <= 126 { 1i128 << x } else { panic!() }; + + // wrong usize / isize + let _ = if x < 32 { 1usize << x } else { panic!() }; + let _ = if x < 64 { 1usize << x } else { panic!() }; + let _ = if x < 32 { 1isize << x } else { panic!() }; + let _ = if x < 64 { 1isize << x } else { panic!() }; + } + + // checked_shr + { + let x = 1u32; + let _ = 1u8.checked_shr(x).unwrap(); + let _ = 1u8.checked_shr(x).unwrap(); + let _ = 1u16.checked_shr(x).unwrap(); + let _ = 1u16.checked_shr(x).unwrap(); + let _ = 1u32.checked_shr(x).unwrap(); + let _ = 1u32.checked_shr(x).unwrap(); + let _ = 1u64.checked_shr(x).unwrap(); + let _ = 1u64.checked_shr(x).unwrap(); + let _ = 1u128.checked_shr(x).unwrap(); + let _ = 1u128.checked_shr(x).unwrap(); + + let _ = 1u8.checked_shr(x).unwrap(); + let _ = 1u16.checked_shr(x).unwrap(); + let _ = 1u32.checked_shr(x).unwrap(); + let _ = 1u64.checked_shr(x).unwrap(); + let _ = 1u128.checked_shr(x).unwrap(); + let _ = 1usize.checked_shr(x).unwrap(); + let _ = 1usize.checked_shr(x).unwrap(); + + let _ = 1i8.checked_shr(x).unwrap(); + let _ = 1i8.checked_shr(x).unwrap(); + let _ = 1i16.checked_shr(x).unwrap(); + let _ = 1i16.checked_shr(x).unwrap(); + let _ = 1i32.checked_shr(x).unwrap(); + let _ = 1i32.checked_shr(x).unwrap(); + let _ = 1i64.checked_shr(x).unwrap(); + let _ = 1i64.checked_shr(x).unwrap(); + let _ = 1i128.checked_shr(x).unwrap(); + let _ = 1i128.checked_shr(x).unwrap(); + + let _ = 1i8.checked_shr(x).unwrap(); + let _ = 1i16.checked_shr(x).unwrap(); + let _ = 1i32.checked_shr(x).unwrap(); + let _ = 1i64.checked_shr(x).unwrap(); + let _ = 1i128.checked_shr(x).unwrap(); + let _ = 1isize.checked_shr(x).unwrap(); + let _ = 1isize.checked_shr(x).unwrap(); + + // Off by 1 + let _ = if x < 9 { 1u8 >> x } else { panic!() }; + let _ = if x <= 8 { 1u8 >> x } else { panic!() }; + let _ = if x < 17 { 1u16 >> x } else { panic!() }; + let _ = if x <= 16 { 1u16 >> x } else { panic!() }; + let _ = if x < 33 { 1u32 >> x } else { panic!() }; + let _ = if x <= 32 { 1u32 >> x } else { panic!() }; + let _ = if x < 65 { 1u64 >> x } else { panic!() }; + let _ = if x <= 64 { 1u64 >> x } else { panic!() }; + let _ = if x < 129 { 1u128 >> x } else { panic!() }; + let _ = if x <= 128 { 1u128 >> x } else { panic!() }; + + let _ = if x < 9 { 1i8 >> x } else { panic!() }; + let _ = if x <= 8 { 1i8 >> x } else { panic!() }; + let _ = if x < 17 { 1i16 >> x } else { panic!() }; + let _ = if x <= 16 { 1i16 >> x } else { panic!() }; + let _ = if x < 33 { 1i32 >> x } else { panic!() }; + let _ = if x <= 32 { 1i32 >> x } else { panic!() }; + let _ = if x < 65 { 1i64 >> x } else { panic!() }; + let _ = if x <= 64 { 1i64 >> x } else { panic!() }; + let _ = if x < 129 { 1i128 >> x } else { panic!() }; + let _ = if x <= 128 { 1i128 >> x } else { panic!() }; + + let _ = if x < 7 { 1u8 >> x } else { panic!() }; + let _ = if x <= 6 { 1u8 >> x } else { panic!() }; + let _ = if x < 15 { 1u16 >> x } else { panic!() }; + let _ = if x <= 14 { 1u16 >> x } else { panic!() }; + let _ = if x < 31 { 1u32 >> x } else { panic!() }; + let _ = if x <= 30 { 1u32 >> x } else { panic!() }; + let _ = if x < 63 { 1u64 >> x } else { panic!() }; + let _ = if x <= 62 { 1u64 >> x } else { panic!() }; + let _ = if x < 127 { 1u128 >> x } else { panic!() }; + let _ = if x <= 126 { 1u128 >> x } else { panic!() }; + + let _ = if x < 7 { 1i8 >> x } else { panic!() }; + let _ = if x <= 6 { 1i8 >> x } else { panic!() }; + let _ = if x < 15 { 1i16 >> x } else { panic!() }; + let _ = if x <= 14 { 1i16 >> x } else { panic!() }; + let _ = if x < 31 { 1i32 >> x } else { panic!() }; + let _ = if x <= 30 { 1i32 >> x } else { panic!() }; + let _ = if x < 63 { 1i64 >> x } else { panic!() }; + let _ = if x <= 62 { 1i64 >> x } else { panic!() }; + let _ = if x < 127 { 1i128 >> x } else { panic!() }; + let _ = if x <= 126 { 1i128 >> x } else { panic!() }; + + // wrong usize / isize + let _ = if x < 32 { 1usize >> x } else { panic!() }; + let _ = if x < 64 { 1usize >> x } else { panic!() }; + let _ = if x < 32 { 1isize >> x } else { panic!() }; + let _ = if x < 64 { 1isize >> x } else { panic!() }; + } + + // alt forms + { + let x = 1; + let _ = 1u8.checked_shl(x).unwrap(); + let _ = 1u8.checked_shl(x).expect("custom message"); + let _ = 1u8.checked_shl(x).unwrap_or_else(|| panic!("{x} formatted message")); + let _ = 1u8.checked_shl(x).unwrap_or_else(|| std::process::abort()); + let _ = 1u8.checked_shl(x).or_else(|| std::process::abort()); + let _ = 1u8.checked_shl(x); + } + + // checked add + { + let x = 1u8; + let _ = x.checked_add(1).unwrap(); + let x = 1u16; + let _ = x.checked_add(1).unwrap(); + let x = 1u32; + let _ = x.checked_add(1).unwrap(); + let x = 1u64; + let _ = x.checked_add(1).unwrap(); + let x = 1u128; + let _ = x.checked_add(1).unwrap(); + + let x = 1i8; + let _ = x.checked_add(1).unwrap(); + let x = 1i16; + let _ = x.checked_add(1).unwrap(); + let x = 1i32; + let _ = x.checked_add(1).unwrap(); + let x = 1i64; + let _ = x.checked_add(1).unwrap(); + let x = 1i128; + let _ = x.checked_add(1).unwrap(); + + let x = 1u8; + let _ = x.checked_add(2).unwrap(); + let x = 1u16; + let _ = x.checked_add(2).unwrap(); + let x = 1u32; + let _ = x.checked_add(2).unwrap(); + let x = 1u64; + let _ = x.checked_add(2).unwrap(); + let x = 1u128; + let _ = x.checked_add(2).unwrap(); + + let x = 1i8; + let _ = x.checked_add(2).unwrap(); + let x = 1i16; + let _ = x.checked_add(2).unwrap(); + let x = 1i32; + let _ = x.checked_add(2).unwrap(); + let x = 1i64; + let _ = x.checked_add(2).unwrap(); + let x = 1i128; + let _ = x.checked_add(2).unwrap(); + + let x = 1u8; + let _ = x.checked_add(1).unwrap(); + let _ = x.checked_add(3).unwrap(); + let _ = x.checked_add(3).unwrap(); + + // Off by one + let x = 1u8; + let _ = if x < u8::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u16; + let _ = if x < u16::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u32; + let _ = if x < u32::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u64; + let _ = if x < u64::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u128; + let _ = if x < u128::MAX - 2 { x + 3 } else { panic!() }; + + let x = 1u8; + let _ = if x < u8::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u16; + let _ = if x < u16::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u32; + let _ = if x < u32::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u64; + let _ = if x < u64::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u128; + let _ = if x < u128::MAX - 2 { x + 1 } else { panic!() }; + + let x = 1u8; + let _ = if x != u8::MAX { x + 2 } else { panic!() }; + } +} diff --git a/tests/ui/manual_checked_op.rs b/tests/ui/manual_checked_op.rs new file mode 100644 index 000000000000..a7f467019c29 --- /dev/null +++ b/tests/ui/manual_checked_op.rs @@ -0,0 +1,283 @@ +#![warn(clippy::manual_checked_op)] +#![allow(clippy::int_plus_one)] + +fn main() { + // checked_shl + { + let x = 1u32; + let _ = if x < 8 { 1u8 << x } else { panic!() }; + let _ = if x <= 7 { 1u8 << x } else { panic!() }; + let _ = if x < 16 { 1u16 << x } else { panic!() }; + let _ = if x <= 15 { 1u16 << x } else { panic!() }; + let _ = if x < 32 { 1u32 << x } else { panic!() }; + let _ = if x <= 31 { 1u32 << x } else { panic!() }; + let _ = if x < 64 { 1u64 << x } else { panic!() }; + let _ = if x <= 63 { 1u64 << x } else { panic!() }; + let _ = if x < 128 { 1u128 << x } else { panic!() }; + let _ = if x <= 127 { 1u128 << x } else { panic!() }; + + let _ = if x < u8::BITS { 1u8 << x } else { panic!() }; + let _ = if x < u16::BITS { 1u16 << x } else { panic!() }; + let _ = if x < u32::BITS { 1u32 << x } else { panic!() }; + let _ = if x < u64::BITS { 1u64 << x } else { panic!() }; + let _ = if x < u128::BITS { 1u128 << x } else { panic!() }; + let _ = if x < usize::BITS { 1usize << x } else { panic!() }; + let _ = if x <= usize::BITS - 1 { 1usize << x } else { panic!() }; + + let _ = if x < 8 { 1i8 << x } else { panic!() }; + let _ = if x <= 7 { 1i8 << x } else { panic!() }; + let _ = if x < 16 { 1i16 << x } else { panic!() }; + let _ = if x <= 15 { 1i16 << x } else { panic!() }; + let _ = if x < 32 { 1i32 << x } else { panic!() }; + let _ = if x <= 31 { 1i32 << x } else { panic!() }; + let _ = if x < 64 { 1i64 << x } else { panic!() }; + let _ = if x <= 63 { 1i64 << x } else { panic!() }; + let _ = if x < 128 { 1i128 << x } else { panic!() }; + let _ = if x <= 127 { 1i128 << x } else { panic!() }; + + let _ = if x < i8::BITS { 1i8 << x } else { panic!() }; + let _ = if x < i16::BITS { 1i16 << x } else { panic!() }; + let _ = if x < i32::BITS { 1i32 << x } else { panic!() }; + let _ = if x < i64::BITS { 1i64 << x } else { panic!() }; + let _ = if x < i128::BITS { 1i128 << x } else { panic!() }; + let _ = if x < isize::BITS { 1isize << x } else { panic!() }; + let _ = if x <= isize::BITS - 1 { 1isize << x } else { panic!() }; + + // Off by 1 + let _ = if x < 9 { 1u8 << x } else { panic!() }; + let _ = if x <= 8 { 1u8 << x } else { panic!() }; + let _ = if x < 17 { 1u16 << x } else { panic!() }; + let _ = if x <= 16 { 1u16 << x } else { panic!() }; + let _ = if x < 33 { 1u32 << x } else { panic!() }; + let _ = if x <= 32 { 1u32 << x } else { panic!() }; + let _ = if x < 65 { 1u64 << x } else { panic!() }; + let _ = if x <= 64 { 1u64 << x } else { panic!() }; + let _ = if x < 129 { 1u128 << x } else { panic!() }; + let _ = if x <= 128 { 1u128 << x } else { panic!() }; + + let _ = if x < 9 { 1i8 << x } else { panic!() }; + let _ = if x <= 8 { 1i8 << x } else { panic!() }; + let _ = if x < 17 { 1i16 << x } else { panic!() }; + let _ = if x <= 16 { 1i16 << x } else { panic!() }; + let _ = if x < 33 { 1i32 << x } else { panic!() }; + let _ = if x <= 32 { 1i32 << x } else { panic!() }; + let _ = if x < 65 { 1i64 << x } else { panic!() }; + let _ = if x <= 64 { 1i64 << x } else { panic!() }; + let _ = if x < 129 { 1i128 << x } else { panic!() }; + let _ = if x <= 128 { 1i128 << x } else { panic!() }; + + let _ = if x < 7 { 1u8 << x } else { panic!() }; + let _ = if x <= 6 { 1u8 << x } else { panic!() }; + let _ = if x < 15 { 1u16 << x } else { panic!() }; + let _ = if x <= 14 { 1u16 << x } else { panic!() }; + let _ = if x < 31 { 1u32 << x } else { panic!() }; + let _ = if x <= 30 { 1u32 << x } else { panic!() }; + let _ = if x < 63 { 1u64 << x } else { panic!() }; + let _ = if x <= 62 { 1u64 << x } else { panic!() }; + let _ = if x < 127 { 1u128 << x } else { panic!() }; + let _ = if x <= 126 { 1u128 << x } else { panic!() }; + + let _ = if x < 7 { 1i8 << x } else { panic!() }; + let _ = if x <= 6 { 1i8 << x } else { panic!() }; + let _ = if x < 15 { 1i16 << x } else { panic!() }; + let _ = if x <= 14 { 1i16 << x } else { panic!() }; + let _ = if x < 31 { 1i32 << x } else { panic!() }; + let _ = if x <= 30 { 1i32 << x } else { panic!() }; + let _ = if x < 63 { 1i64 << x } else { panic!() }; + let _ = if x <= 62 { 1i64 << x } else { panic!() }; + let _ = if x < 127 { 1i128 << x } else { panic!() }; + let _ = if x <= 126 { 1i128 << x } else { panic!() }; + + // wrong usize / isize + let _ = if x < 32 { 1usize << x } else { panic!() }; + let _ = if x < 64 { 1usize << x } else { panic!() }; + let _ = if x < 32 { 1isize << x } else { panic!() }; + let _ = if x < 64 { 1isize << x } else { panic!() }; + } + + // checked_shr + { + let x = 1u32; + let _ = if x < 8 { 1u8 >> x } else { panic!() }; + let _ = if x <= 7 { 1u8 >> x } else { panic!() }; + let _ = if x < 16 { 1u16 >> x } else { panic!() }; + let _ = if x <= 15 { 1u16 >> x } else { panic!() }; + let _ = if x < 32 { 1u32 >> x } else { panic!() }; + let _ = if x <= 31 { 1u32 >> x } else { panic!() }; + let _ = if x < 64 { 1u64 >> x } else { panic!() }; + let _ = if x <= 63 { 1u64 >> x } else { panic!() }; + let _ = if x < 128 { 1u128 >> x } else { panic!() }; + let _ = if x <= 127 { 1u128 >> x } else { panic!() }; + + let _ = if x < u8::BITS { 1u8 >> x } else { panic!() }; + let _ = if x < u16::BITS { 1u16 >> x } else { panic!() }; + let _ = if x < u32::BITS { 1u32 >> x } else { panic!() }; + let _ = if x < u64::BITS { 1u64 >> x } else { panic!() }; + let _ = if x < u128::BITS { 1u128 >> x } else { panic!() }; + let _ = if x < usize::BITS { 1usize >> x } else { panic!() }; + let _ = if x <= usize::BITS - 1 { 1usize >> x } else { panic!() }; + + let _ = if x < 8 { 1i8 >> x } else { panic!() }; + let _ = if x <= 7 { 1i8 >> x } else { panic!() }; + let _ = if x < 16 { 1i16 >> x } else { panic!() }; + let _ = if x <= 15 { 1i16 >> x } else { panic!() }; + let _ = if x < 32 { 1i32 >> x } else { panic!() }; + let _ = if x <= 31 { 1i32 >> x } else { panic!() }; + let _ = if x < 64 { 1i64 >> x } else { panic!() }; + let _ = if x <= 63 { 1i64 >> x } else { panic!() }; + let _ = if x < 128 { 1i128 >> x } else { panic!() }; + let _ = if x <= 127 { 1i128 >> x } else { panic!() }; + + let _ = if x < i8::BITS { 1i8 >> x } else { panic!() }; + let _ = if x < i16::BITS { 1i16 >> x } else { panic!() }; + let _ = if x < i32::BITS { 1i32 >> x } else { panic!() }; + let _ = if x < i64::BITS { 1i64 >> x } else { panic!() }; + let _ = if x < i128::BITS { 1i128 >> x } else { panic!() }; + let _ = if x < isize::BITS { 1isize >> x } else { panic!() }; + let _ = if x <= isize::BITS - 1 { 1isize >> x } else { panic!() }; + + // Off by 1 + let _ = if x < 9 { 1u8 >> x } else { panic!() }; + let _ = if x <= 8 { 1u8 >> x } else { panic!() }; + let _ = if x < 17 { 1u16 >> x } else { panic!() }; + let _ = if x <= 16 { 1u16 >> x } else { panic!() }; + let _ = if x < 33 { 1u32 >> x } else { panic!() }; + let _ = if x <= 32 { 1u32 >> x } else { panic!() }; + let _ = if x < 65 { 1u64 >> x } else { panic!() }; + let _ = if x <= 64 { 1u64 >> x } else { panic!() }; + let _ = if x < 129 { 1u128 >> x } else { panic!() }; + let _ = if x <= 128 { 1u128 >> x } else { panic!() }; + + let _ = if x < 9 { 1i8 >> x } else { panic!() }; + let _ = if x <= 8 { 1i8 >> x } else { panic!() }; + let _ = if x < 17 { 1i16 >> x } else { panic!() }; + let _ = if x <= 16 { 1i16 >> x } else { panic!() }; + let _ = if x < 33 { 1i32 >> x } else { panic!() }; + let _ = if x <= 32 { 1i32 >> x } else { panic!() }; + let _ = if x < 65 { 1i64 >> x } else { panic!() }; + let _ = if x <= 64 { 1i64 >> x } else { panic!() }; + let _ = if x < 129 { 1i128 >> x } else { panic!() }; + let _ = if x <= 128 { 1i128 >> x } else { panic!() }; + + let _ = if x < 7 { 1u8 >> x } else { panic!() }; + let _ = if x <= 6 { 1u8 >> x } else { panic!() }; + let _ = if x < 15 { 1u16 >> x } else { panic!() }; + let _ = if x <= 14 { 1u16 >> x } else { panic!() }; + let _ = if x < 31 { 1u32 >> x } else { panic!() }; + let _ = if x <= 30 { 1u32 >> x } else { panic!() }; + let _ = if x < 63 { 1u64 >> x } else { panic!() }; + let _ = if x <= 62 { 1u64 >> x } else { panic!() }; + let _ = if x < 127 { 1u128 >> x } else { panic!() }; + let _ = if x <= 126 { 1u128 >> x } else { panic!() }; + + let _ = if x < 7 { 1i8 >> x } else { panic!() }; + let _ = if x <= 6 { 1i8 >> x } else { panic!() }; + let _ = if x < 15 { 1i16 >> x } else { panic!() }; + let _ = if x <= 14 { 1i16 >> x } else { panic!() }; + let _ = if x < 31 { 1i32 >> x } else { panic!() }; + let _ = if x <= 30 { 1i32 >> x } else { panic!() }; + let _ = if x < 63 { 1i64 >> x } else { panic!() }; + let _ = if x <= 62 { 1i64 >> x } else { panic!() }; + let _ = if x < 127 { 1i128 >> x } else { panic!() }; + let _ = if x <= 126 { 1i128 >> x } else { panic!() }; + + // wrong usize / isize + let _ = if x < 32 { 1usize >> x } else { panic!() }; + let _ = if x < 64 { 1usize >> x } else { panic!() }; + let _ = if x < 32 { 1isize >> x } else { panic!() }; + let _ = if x < 64 { 1isize >> x } else { panic!() }; + } + + // alt forms + { + let x = 1; + let _ = if x >= 8 { panic!() } else { 1u8 << x }; + let _ = if x < 8 { 1u8 << x } else { panic!("custom message") }; + let _ = if x < 8 { + 1u8 << x + } else { + panic!("{x} formatted message") + }; + let _ = if x < 8 { 1u8 << x } else { std::process::abort() }; + let _ = if x < 8 { Some(1u8 << x) } else { std::process::abort() }; + let _ = if x < 8 { Some(1u8 << x) } else { None }; + } + + // checked add + { + let x = 1u8; + let _ = if x != u8::MAX { x + 1 } else { panic!() }; + let x = 1u16; + let _ = if x != u16::MAX { x + 1 } else { panic!() }; + let x = 1u32; + let _ = if x != u32::MAX { x + 1 } else { panic!() }; + let x = 1u64; + let _ = if x != u64::MAX { x + 1 } else { panic!() }; + let x = 1u128; + let _ = if x != u128::MAX { x + 1 } else { panic!() }; + + let x = 1i8; + let _ = if x != i8::MAX { x + 1 } else { panic!() }; + let x = 1i16; + let _ = if x != i16::MAX { x + 1 } else { panic!() }; + let x = 1i32; + let _ = if x != i32::MAX { x + 1 } else { panic!() }; + let x = 1i64; + let _ = if x != i64::MAX { x + 1 } else { panic!() }; + let x = 1i128; + let _ = if x != i128::MAX { x + 1 } else { panic!() }; + + let x = 1u8; + let _ = if x < u8::MAX - 2 { x + 2 } else { panic!() }; + let x = 1u16; + let _ = if x < u16::MAX - 2 { x + 2 } else { panic!() }; + let x = 1u32; + let _ = if x < u32::MAX - 2 { x + 2 } else { panic!() }; + let x = 1u64; + let _ = if x < u64::MAX - 2 { x + 2 } else { panic!() }; + let x = 1u128; + let _ = if x < u128::MAX - 2 { x + 2 } else { panic!() }; + + let x = 1i8; + let _ = if x < i8::MAX - 2 { x + 2 } else { panic!() }; + let x = 1i16; + let _ = if x < i16::MAX - 2 { x + 2 } else { panic!() }; + let x = 1i32; + let _ = if x < i32::MAX - 2 { x + 2 } else { panic!() }; + let x = 1i64; + let _ = if x < i64::MAX - 2 { x + 2 } else { panic!() }; + let x = 1i128; + let _ = if x < i128::MAX - 2 { x + 2 } else { panic!() }; + + let x = 1u8; + let _ = if u8::MAX != x { 1 + x } else { panic!() }; + let _ = if u8::MAX - 3 > x { x + 3 } else { panic!() }; + let _ = if x < u8::MAX - 3 { 3 + x } else { panic!() }; + + // Off by one + let x = 1u8; + let _ = if x < u8::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u16; + let _ = if x < u16::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u32; + let _ = if x < u32::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u64; + let _ = if x < u64::MAX - 2 { x + 3 } else { panic!() }; + let x = 1u128; + let _ = if x < u128::MAX - 2 { x + 3 } else { panic!() }; + + let x = 1u8; + let _ = if x < u8::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u16; + let _ = if x < u16::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u32; + let _ = if x < u32::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u64; + let _ = if x < u64::MAX - 2 { x + 1 } else { panic!() }; + let x = 1u128; + let _ = if x < u128::MAX - 2 { x + 1 } else { panic!() }; + + let x = 1u8; + let _ = if x != u8::MAX { x + 2 } else { panic!() }; + } +} diff --git a/tests/ui/manual_checked_op.stderr b/tests/ui/manual_checked_op.stderr new file mode 100644 index 000000000000..496bf485fc54 --- /dev/null +++ b/tests/ui/manual_checked_op.stderr @@ -0,0 +1,592 @@ +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:8:17 + | +LL | let _ = if x < 8 { 1u8 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).unwrap()` + | + = note: `-D clippy::manual-checked-op` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_checked_op)]` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:9:17 + | +LL | let _ = if x <= 7 { 1u8 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:10:17 + | +LL | let _ = if x < 16 { 1u16 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u16.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:11:17 + | +LL | let _ = if x <= 15 { 1u16 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u16.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:12:17 + | +LL | let _ = if x < 32 { 1u32 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u32.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:13:17 + | +LL | let _ = if x <= 31 { 1u32 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u32.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:14:17 + | +LL | let _ = if x < 64 { 1u64 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u64.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:15:17 + | +LL | let _ = if x <= 63 { 1u64 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u64.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:16:17 + | +LL | let _ = if x < 128 { 1u128 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u128.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:17:17 + | +LL | let _ = if x <= 127 { 1u128 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u128.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:19:17 + | +LL | let _ = if x < u8::BITS { 1u8 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:20:17 + | +LL | let _ = if x < u16::BITS { 1u16 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u16.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:21:17 + | +LL | let _ = if x < u32::BITS { 1u32 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u32.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:22:17 + | +LL | let _ = if x < u64::BITS { 1u64 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u64.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:23:17 + | +LL | let _ = if x < u128::BITS { 1u128 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u128.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:24:17 + | +LL | let _ = if x < usize::BITS { 1usize << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1usize.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:25:17 + | +LL | let _ = if x <= usize::BITS - 1 { 1usize << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1usize.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:27:17 + | +LL | let _ = if x < 8 { 1i8 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i8.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:28:17 + | +LL | let _ = if x <= 7 { 1i8 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i8.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:29:17 + | +LL | let _ = if x < 16 { 1i16 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i16.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:30:17 + | +LL | let _ = if x <= 15 { 1i16 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i16.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:31:17 + | +LL | let _ = if x < 32 { 1i32 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i32.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:32:17 + | +LL | let _ = if x <= 31 { 1i32 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i32.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:33:17 + | +LL | let _ = if x < 64 { 1i64 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i64.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:34:17 + | +LL | let _ = if x <= 63 { 1i64 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i64.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:35:17 + | +LL | let _ = if x < 128 { 1i128 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i128.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:36:17 + | +LL | let _ = if x <= 127 { 1i128 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i128.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:38:17 + | +LL | let _ = if x < i8::BITS { 1i8 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i8.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:39:17 + | +LL | let _ = if x < i16::BITS { 1i16 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i16.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:40:17 + | +LL | let _ = if x < i32::BITS { 1i32 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i32.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:41:17 + | +LL | let _ = if x < i64::BITS { 1i64 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i64.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:42:17 + | +LL | let _ = if x < i128::BITS { 1i128 << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i128.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:43:17 + | +LL | let _ = if x < isize::BITS { 1isize << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1isize.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:44:17 + | +LL | let _ = if x <= isize::BITS - 1 { 1isize << x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1isize.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:101:17 + | +LL | let _ = if x < 8 { 1u8 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:102:17 + | +LL | let _ = if x <= 7 { 1u8 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:103:17 + | +LL | let _ = if x < 16 { 1u16 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u16.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:104:17 + | +LL | let _ = if x <= 15 { 1u16 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u16.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:105:17 + | +LL | let _ = if x < 32 { 1u32 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u32.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:106:17 + | +LL | let _ = if x <= 31 { 1u32 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u32.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:107:17 + | +LL | let _ = if x < 64 { 1u64 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u64.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:108:17 + | +LL | let _ = if x <= 63 { 1u64 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u64.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:109:17 + | +LL | let _ = if x < 128 { 1u128 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u128.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:110:17 + | +LL | let _ = if x <= 127 { 1u128 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u128.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:112:17 + | +LL | let _ = if x < u8::BITS { 1u8 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:113:17 + | +LL | let _ = if x < u16::BITS { 1u16 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u16.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:114:17 + | +LL | let _ = if x < u32::BITS { 1u32 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u32.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:115:17 + | +LL | let _ = if x < u64::BITS { 1u64 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u64.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:116:17 + | +LL | let _ = if x < u128::BITS { 1u128 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u128.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:117:17 + | +LL | let _ = if x < usize::BITS { 1usize >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1usize.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:118:17 + | +LL | let _ = if x <= usize::BITS - 1 { 1usize >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1usize.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:120:17 + | +LL | let _ = if x < 8 { 1i8 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i8.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:121:17 + | +LL | let _ = if x <= 7 { 1i8 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i8.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:122:17 + | +LL | let _ = if x < 16 { 1i16 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i16.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:123:17 + | +LL | let _ = if x <= 15 { 1i16 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i16.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:124:17 + | +LL | let _ = if x < 32 { 1i32 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i32.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:125:17 + | +LL | let _ = if x <= 31 { 1i32 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i32.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:126:17 + | +LL | let _ = if x < 64 { 1i64 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i64.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:127:17 + | +LL | let _ = if x <= 63 { 1i64 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i64.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:128:17 + | +LL | let _ = if x < 128 { 1i128 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i128.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:129:17 + | +LL | let _ = if x <= 127 { 1i128 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i128.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:131:17 + | +LL | let _ = if x < i8::BITS { 1i8 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i8.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:132:17 + | +LL | let _ = if x < i16::BITS { 1i16 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i16.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:133:17 + | +LL | let _ = if x < i32::BITS { 1i32 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i32.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:134:17 + | +LL | let _ = if x < i64::BITS { 1i64 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i64.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:135:17 + | +LL | let _ = if x < i128::BITS { 1i128 >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1i128.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:136:17 + | +LL | let _ = if x < isize::BITS { 1isize >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1isize.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shr` + --> $DIR/manual_checked_op.rs:137:17 + | +LL | let _ = if x <= isize::BITS - 1 { 1isize >> x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1isize.checked_shr(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:194:17 + | +LL | let _ = if x >= 8 { panic!() } else { 1u8 << x }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).unwrap()` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:195:17 + | +LL | let _ = if x < 8 { 1u8 << x } else { panic!("custom message") }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).expect("custom message")` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:196:17 + | +LL | let _ = if x < 8 { + | _________________^ +LL | | 1u8 << x +LL | | } else { +LL | | panic!("{x} formatted message") +LL | | }; + | |_________^ help: try: `1u8.checked_shl(x).unwrap_or_else(|| panic!("{x} formatted message"))` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:201:17 + | +LL | let _ = if x < 8 { 1u8 << x } else { std::process::abort() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).unwrap_or_else(|| std::process::abort())` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:202:17 + | +LL | let _ = if x < 8 { Some(1u8 << x) } else { std::process::abort() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x).or_else(|| std::process::abort())` + +error: manual implementation of `checked_shl` + --> $DIR/manual_checked_op.rs:203:17 + | +LL | let _ = if x < 8 { Some(1u8 << x) } else { None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1u8.checked_shl(x)` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:209:17 + | +LL | let _ = if x != u8::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:211:17 + | +LL | let _ = if x != u16::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:213:17 + | +LL | let _ = if x != u32::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:215:17 + | +LL | let _ = if x != u64::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:217:17 + | +LL | let _ = if x != u128::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:220:17 + | +LL | let _ = if x != i8::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:222:17 + | +LL | let _ = if x != i16::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:224:17 + | +LL | let _ = if x != i32::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:226:17 + | +LL | let _ = if x != i64::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:228:17 + | +LL | let _ = if x != i128::MAX { x + 1 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:231:17 + | +LL | let _ = if x < u8::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:233:17 + | +LL | let _ = if x < u16::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:235:17 + | +LL | let _ = if x < u32::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:237:17 + | +LL | let _ = if x < u64::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:239:17 + | +LL | let _ = if x < u128::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:242:17 + | +LL | let _ = if x < i8::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:244:17 + | +LL | let _ = if x < i16::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:246:17 + | +LL | let _ = if x < i32::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:248:17 + | +LL | let _ = if x < i64::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:250:17 + | +LL | let _ = if x < i128::MAX - 2 { x + 2 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(2).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:253:17 + | +LL | let _ = if u8::MAX != x { 1 + x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(1).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:254:17 + | +LL | let _ = if u8::MAX - 3 > x { x + 3 } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(3).unwrap()` + +error: manual implementation of `checked_add` + --> $DIR/manual_checked_op.rs:255:17 + | +LL | let _ = if x < u8::MAX - 3 { 3 + x } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.checked_add(3).unwrap()` + +error: aborting due to 97 previous errors +