@@ -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;
@@ -834,17 +836,43 @@ declare_clippy_lint! {
834836 "explicit self-assignment"
835837}
836838
839+ declare_clippy_lint ! {
840+ /// ### What it does
841+ /// Checks for manual implementation of `midpoint`.
842+ ///
843+ /// ### Why is this bad?
844+ /// Using `(x + y) / 2` might cause an overflow on the intermediate
845+ /// addition result.
846+ ///
847+ /// ### Example
848+ /// ```no_run
849+ /// # let a: u32 = 0;
850+ /// let c = (a + 10) / 2;
851+ /// ```
852+ /// Use instead:
853+ /// ```no_run
854+ /// # let a: u32 = 0;
855+ /// let c = u32::midpoint(a, 10);
856+ /// ```
857+ #[ clippy:: version = "1.87.0" ]
858+ pub MANUAL_MIDPOINT ,
859+ pedantic,
860+ "manual implementation of `midpoint` which can overflow"
861+ }
862+
837863pub struct Operators {
838864 arithmetic_context : numeric_arithmetic:: Context ,
839865 verbose_bit_mask_threshold : u64 ,
840866 modulo_arithmetic_allow_comparison_to_zero : bool ,
867+ msrv : Msrv ,
841868}
842869impl Operators {
843870 pub fn new ( conf : & ' static Conf ) -> Self {
844871 Self {
845872 arithmetic_context : numeric_arithmetic:: Context :: default ( ) ,
846873 verbose_bit_mask_threshold : conf. verbose_bit_mask_threshold ,
847874 modulo_arithmetic_allow_comparison_to_zero : conf. allow_comparison_to_zero ,
875+ msrv : conf. msrv . clone ( ) ,
848876 }
849877 }
850878}
@@ -876,6 +904,7 @@ impl_lint_pass!(Operators => [
876904 NEEDLESS_BITWISE_BOOL ,
877905 PTR_EQ ,
878906 SELF_ASSIGNMENT ,
907+ MANUAL_MIDPOINT ,
879908] ) ;
880909
881910impl < ' tcx > LateLintPass < ' tcx > for Operators {
@@ -893,6 +922,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
893922 identity_op:: check ( cx, e, op. node , lhs, rhs) ;
894923 needless_bitwise_bool:: check ( cx, e, op. node , lhs, rhs) ;
895924 ptr_eq:: check ( cx, e, op. node , lhs, rhs) ;
925+ manual_midpoint:: check ( cx, e, op. node , lhs, rhs, & self . msrv ) ;
896926 }
897927 self . arithmetic_context . check_binary ( cx, e, op. node , lhs, rhs) ;
898928 bit_mask:: check ( cx, e, op. node , lhs, rhs) ;
@@ -943,6 +973,8 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
943973 fn check_body_post ( & mut self , cx : & LateContext < ' tcx > , b : & Body < ' _ > ) {
944974 self . arithmetic_context . body_post ( cx, b) ;
945975 }
976+
977+ extract_msrv_attr ! ( LateContext ) ;
946978}
947979
948980fn macro_with_not_op ( e : & Expr < ' _ > ) -> bool {
0 commit comments