@@ -107,7 +107,9 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
107
107
} ) = higher:: If :: hir ( expr)
108
108
&& let ExprKind :: Binary ( ref cond_op, cond_left, cond_right) = cond. kind
109
109
{
110
- check_manual_check ( cx, cond_op, cond_left, cond_right, if_block, else_block, & self . msrv ) ;
110
+ check_manual_check (
111
+ cx, expr, cond_op, cond_left, cond_right, if_block, else_block, & self . msrv ,
112
+ ) ;
111
113
}
112
114
}
113
115
@@ -117,6 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
117
119
#[ allow( clippy:: too_many_arguments) ]
118
120
fn check_manual_check < ' tcx > (
119
121
cx : & LateContext < ' tcx > ,
122
+ expr : & Expr < ' tcx > ,
120
123
condition : & BinOp ,
121
124
left_hand : & Expr < ' tcx > ,
122
125
right_hand : & Expr < ' tcx > ,
@@ -127,12 +130,40 @@ fn check_manual_check<'tcx>(
127
130
let ty = cx. typeck_results ( ) . expr_ty ( left_hand) ;
128
131
if ty. is_numeric ( ) && !ty. is_signed ( ) {
129
132
match condition. node {
130
- BinOpKind :: Gt | BinOpKind :: Ge => {
131
- check_gt ( cx, condition. span , left_hand, right_hand, if_block, else_block, msrv) ;
132
- } ,
133
- BinOpKind :: Lt | BinOpKind :: Le => {
134
- check_gt ( cx, condition. span , right_hand, left_hand, if_block, else_block, msrv) ;
135
- } ,
133
+ BinOpKind :: Gt | BinOpKind :: Ge => check_gt (
134
+ cx,
135
+ condition. span ,
136
+ expr. span ,
137
+ left_hand,
138
+ right_hand,
139
+ if_block,
140
+ else_block,
141
+ msrv,
142
+ matches ! (
143
+ clippy_utils:: get_parent_expr( cx, expr) ,
144
+ Some ( Expr {
145
+ kind: ExprKind :: If ( ..) ,
146
+ ..
147
+ } )
148
+ ) ,
149
+ ) ,
150
+ BinOpKind :: Lt | BinOpKind :: Le => check_gt (
151
+ cx,
152
+ condition. span ,
153
+ expr. span ,
154
+ right_hand,
155
+ left_hand,
156
+ if_block,
157
+ else_block,
158
+ msrv,
159
+ matches ! (
160
+ clippy_utils:: get_parent_expr( cx, expr) ,
161
+ Some ( Expr {
162
+ kind: ExprKind :: If ( ..) ,
163
+ ..
164
+ } )
165
+ ) ,
166
+ ) ,
136
167
_ => { } ,
137
168
}
138
169
}
@@ -142,16 +173,28 @@ fn check_manual_check<'tcx>(
142
173
fn check_gt (
143
174
cx : & LateContext < ' _ > ,
144
175
condition_span : Span ,
176
+ expr_span : Span ,
145
177
big_var : & Expr < ' _ > ,
146
178
little_var : & Expr < ' _ > ,
147
179
if_block : & Expr < ' _ > ,
148
180
else_block : & Expr < ' _ > ,
149
181
msrv : & Msrv ,
182
+ is_composited : bool ,
150
183
) {
151
184
if let Some ( big_var) = Var :: new ( big_var)
152
185
&& let Some ( little_var) = Var :: new ( little_var)
153
186
{
154
- check_subtraction ( cx, condition_span, big_var, little_var, if_block, else_block, msrv) ;
187
+ check_subtraction (
188
+ cx,
189
+ condition_span,
190
+ expr_span,
191
+ big_var,
192
+ little_var,
193
+ if_block,
194
+ else_block,
195
+ msrv,
196
+ is_composited,
197
+ ) ;
155
198
}
156
199
}
157
200
@@ -173,11 +216,13 @@ impl Var {
173
216
fn check_subtraction (
174
217
cx : & LateContext < ' _ > ,
175
218
condition_span : Span ,
219
+ expr_span : Span ,
176
220
big_var : Var ,
177
221
little_var : Var ,
178
222
if_block : & Expr < ' _ > ,
179
223
else_block : & Expr < ' _ > ,
180
224
msrv : & Msrv ,
225
+ is_composited : bool ,
181
226
) {
182
227
let if_block = peel_blocks ( if_block) ;
183
228
let else_block = peel_blocks ( else_block) ;
@@ -189,7 +234,17 @@ fn check_subtraction(
189
234
}
190
235
// If the subtraction is done in the `else` block, then we need to also revert the two
191
236
// variables as it means that the check was reverted too.
192
- check_subtraction ( cx, condition_span, little_var, big_var, else_block, if_block, msrv) ;
237
+ check_subtraction (
238
+ cx,
239
+ condition_span,
240
+ expr_span,
241
+ little_var,
242
+ big_var,
243
+ else_block,
244
+ if_block,
245
+ msrv,
246
+ is_composited,
247
+ ) ;
193
248
return ;
194
249
}
195
250
if is_integer_literal ( else_block, 0 )
@@ -205,13 +260,18 @@ fn check_subtraction(
205
260
&& let Some ( little_var_snippet) = snippet_opt ( cx, little_var. span )
206
261
&& ( !is_in_const_context ( cx) || msrv. meets ( msrvs:: SATURATING_SUB_CONST ) )
207
262
{
263
+ let sugg = format ! (
264
+ "{}{big_var_snippet}.saturating_sub({little_var_snippet}){}" ,
265
+ if is_composited { "{ " } else { "" } ,
266
+ if is_composited { " }" } else { "" }
267
+ ) ;
208
268
span_lint_and_sugg (
209
269
cx,
210
270
IMPLICIT_SATURATING_SUB ,
211
- else_block . span ,
271
+ expr_span ,
212
272
"manual arithmetic check found" ,
213
273
"replace it with" ,
214
- format ! ( "{big_var_snippet}.saturating_sub({little_var_snippet})" ) ,
274
+ sugg ,
215
275
Applicability :: MachineApplicable ,
216
276
) ;
217
277
}
0 commit comments