@@ -11,6 +11,7 @@ mod float_cmp;
1111mod float_equality_without_abs;
1212mod identity_op;
1313mod integer_division;
14+ mod manual_midpoint;
1415mod misrefactored_assign_op;
1516mod modulo_arithmetic;
1617mod modulo_one;
@@ -24,6 +25,7 @@ mod verbose_bit_mask;
2425pub ( crate ) mod arithmetic_side_effects;
2526
2627use clippy_config:: Conf ;
28+ use clippy_utils:: msrvs:: Msrv ;
2729use rustc_hir:: { Body , Expr , ExprKind , UnOp } ;
2830use rustc_lint:: { LateContext , LateLintPass } ;
2931use rustc_session:: impl_lint_pass;
@@ -837,17 +839,43 @@ declare_clippy_lint! {
837839 "explicit self-assignment"
838840}
839841
842+ declare_clippy_lint ! {
843+ /// ### What it does
844+ /// Checks for manual implementation of `midpoint`.
845+ ///
846+ /// ### Why is this bad?
847+ /// Using `(x + y) / 2` might cause an overflow on the intermediate
848+ /// addition result.
849+ ///
850+ /// ### Example
851+ /// ```no_run
852+ /// # let a: u32 = 0;
853+ /// let c = (a + 10) / 2;
854+ /// ```
855+ /// Use instead:
856+ /// ```no_run
857+ /// # let a: u32 = 0;
858+ /// let c = u32::midpoint(a, 10);
859+ /// ```
860+ #[ clippy:: version = "1.85.0" ]
861+ pub MANUAL_MIDPOINT ,
862+ correctness,
863+ "manual implementation of `midpoint` which can overflow"
864+ }
865+
840866pub struct Operators {
841867 arithmetic_context : numeric_arithmetic:: Context ,
842868 verbose_bit_mask_threshold : u64 ,
843869 modulo_arithmetic_allow_comparison_to_zero : bool ,
870+ msrv : Msrv ,
844871}
845872impl Operators {
846873 pub fn new ( conf : & ' static Conf ) -> Self {
847874 Self {
848875 arithmetic_context : numeric_arithmetic:: Context :: default ( ) ,
849876 verbose_bit_mask_threshold : conf. verbose_bit_mask_threshold ,
850877 modulo_arithmetic_allow_comparison_to_zero : conf. allow_comparison_to_zero ,
878+ msrv : conf. msrv . clone ( ) ,
851879 }
852880 }
853881}
@@ -879,6 +907,7 @@ impl_lint_pass!(Operators => [
879907 NEEDLESS_BITWISE_BOOL ,
880908 PTR_EQ ,
881909 SELF_ASSIGNMENT ,
910+ MANUAL_MIDPOINT ,
882911] ) ;
883912
884913impl < ' tcx > LateLintPass < ' tcx > for Operators {
@@ -896,6 +925,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
896925 identity_op:: check ( cx, e, op. node , lhs, rhs) ;
897926 needless_bitwise_bool:: check ( cx, e, op. node , lhs, rhs) ;
898927 ptr_eq:: check ( cx, e, op. node , lhs, rhs) ;
928+ manual_midpoint:: check ( cx, e, op. node , lhs, rhs, & self . msrv ) ;
899929 }
900930 self . arithmetic_context . check_binary ( cx, e, op. node , lhs, rhs) ;
901931 bit_mask:: check ( cx, e, op. node , lhs, rhs) ;
@@ -946,6 +976,8 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
946976 fn check_body_post ( & mut self , cx : & LateContext < ' tcx > , b : & Body < ' _ > ) {
947977 self . arithmetic_context . body_post ( cx, b) ;
948978 }
979+
980+ extract_msrv_attr ! ( LateContext ) ;
949981}
950982
951983fn macro_with_not_op ( e : & Expr < ' _ > ) -> bool {
0 commit comments