@@ -4,18 +4,19 @@ use clippy_utils::source::snippet_with_applicability;
44use clippy_utils:: sym;
55use rustc_ast:: ast;
66use rustc_errors:: Applicability ;
7- use rustc_hir as hir;
87use rustc_hir:: def:: Res ;
8+ use rustc_hir:: { self as hir, Expr } ;
99use rustc_lint:: LateContext ;
10+ use rustc_middle:: ty:: Ty ;
1011use rustc_middle:: ty:: layout:: LayoutOf ;
1112use rustc_span:: Symbol ;
1213
13- pub fn check (
14+ pub fn check_unwrap_or (
1415 cx : & LateContext < ' _ > ,
15- expr : & hir :: Expr < ' _ > ,
16- arith_lhs : & hir :: Expr < ' _ > ,
17- arith_rhs : & hir :: Expr < ' _ > ,
18- unwrap_arg : & hir :: Expr < ' _ > ,
16+ expr : & Expr < ' _ > ,
17+ arith_lhs : & Expr < ' _ > ,
18+ arith_rhs : & Expr < ' _ > ,
19+ unwrap_arg : & Expr < ' _ > ,
1920 arith : Symbol ,
2021) {
2122 let ty = cx. typeck_results ( ) . expr_ty ( arith_lhs) ;
@@ -31,6 +32,40 @@ pub fn check(
3132 return ;
3233 } ;
3334
35+ check ( cx, expr, arith_lhs, arith_rhs, ty, mm, checked_arith) ;
36+ }
37+
38+ pub ( super ) fn check_sub_unwrap_or_default (
39+ cx : & LateContext < ' _ > ,
40+ expr : & Expr < ' _ > ,
41+ arith_lhs : & Expr < ' _ > ,
42+ arith_rhs : & Expr < ' _ > ,
43+ ) {
44+ let ty = cx. typeck_results ( ) . expr_ty ( arith_lhs) ;
45+ if !ty. is_integral ( ) {
46+ return ;
47+ }
48+
49+ let mm = if ty. is_signed ( ) {
50+ return ; // iN::default() is 0, which is neither MIN nor MAX
51+ } else {
52+ MinMax :: Min // uN::default() is 0, which is also the MIN
53+ } ;
54+
55+ let checked_arith = CheckedArith :: Sub ;
56+
57+ check ( cx, expr, arith_lhs, arith_rhs, ty, mm, checked_arith) ;
58+ }
59+
60+ fn check (
61+ cx : & LateContext < ' _ > ,
62+ expr : & Expr < ' _ > ,
63+ arith_lhs : & Expr < ' _ > ,
64+ arith_rhs : & Expr < ' _ > ,
65+ ty : Ty < ' _ > ,
66+ mm : MinMax ,
67+ checked_arith : CheckedArith ,
68+ ) {
3469 {
3570 use self :: MinMax :: { Max , Min } ;
3671 use self :: Sign :: { Neg , Pos } ;
@@ -41,13 +76,13 @@ pub fn check(
4176 return ;
4277 } ;
4378
44- match ( & checked_arith, sign, mm) {
79+ match ( checked_arith, sign, mm) {
4580 ( Add , Pos , Max ) | ( Add , Neg , Min ) | ( Sub , Neg , Max ) | ( Sub , Pos , Min ) => ( ) ,
4681 // "mul" is omitted because lhs can be negative.
4782 _ => return ,
4883 }
4984 } else {
50- match ( mm, & checked_arith) {
85+ match ( mm, checked_arith) {
5186 ( Max , Add | Mul ) | ( Min , Sub ) => ( ) ,
5287 _ => return ,
5388 }
@@ -71,6 +106,7 @@ pub fn check(
71106 ) ;
72107}
73108
109+ #[ derive( Clone , Copy ) ]
74110enum CheckedArith {
75111 Add ,
76112 Sub ,
@@ -88,7 +124,7 @@ impl CheckedArith {
88124 Some ( res)
89125 }
90126
91- fn as_saturating ( & self ) -> & ' static str {
127+ fn as_saturating ( self ) -> & ' static str {
92128 match self {
93129 Self :: Add => "saturating_add" ,
94130 Self :: Sub => "saturating_sub" ,
@@ -103,7 +139,7 @@ enum MinMax {
103139 Max ,
104140}
105141
106- fn is_min_or_max ( cx : & LateContext < ' _ > , expr : & hir :: Expr < ' _ > ) -> Option < MinMax > {
142+ fn is_min_or_max ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> Option < MinMax > {
107143 // `T::max_value()` `T::min_value()` inherent methods
108144 if let hir:: ExprKind :: Call ( func, [ ] ) = & expr. kind
109145 && let hir:: ExprKind :: Path ( hir:: QPath :: TypeRelative ( _, segment) ) = & func. kind
@@ -141,7 +177,7 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
141177 ( 0 , if bits == 128 { !0 } else { ( 1 << bits) - 1 } )
142178 } ;
143179
144- let check_lit = |expr : & hir :: Expr < ' _ > , check_min : bool | {
180+ let check_lit = |expr : & Expr < ' _ > , check_min : bool | {
145181 if let hir:: ExprKind :: Lit ( lit) = & expr. kind
146182 && let ast:: LitKind :: Int ( value, _) = lit. node
147183 {
@@ -176,7 +212,7 @@ enum Sign {
176212 Neg ,
177213}
178214
179- fn lit_sign ( expr : & hir :: Expr < ' _ > ) -> Option < Sign > {
215+ fn lit_sign ( expr : & Expr < ' _ > ) -> Option < Sign > {
180216 if let hir:: ExprKind :: Unary ( hir:: UnOp :: Neg , inner) = & expr. kind {
181217 if let hir:: ExprKind :: Lit ( ..) = & inner. kind {
182218 return Some ( Sign :: Neg ) ;
0 commit comments