@@ -203,108 +203,106 @@ fn expr_return_none_or_err(
203
203
}
204
204
}
205
205
206
- impl QuestionMark {
207
- fn inside_try_block ( & self ) -> bool {
208
- self . try_block_depth_stack . last ( ) > Some ( & 0 )
209
- }
210
-
211
- /// Checks if the given expression on the given context matches the following structure:
212
- ///
213
- /// ```ignore
214
- /// if option.is_none() {
215
- /// return None;
216
- /// }
217
- /// ```
218
- ///
219
- /// ```ignore
220
- /// if result.is_err() {
221
- /// return result;
222
- /// }
223
- /// ```
224
- ///
225
- /// If it matches, it will suggest to use the question mark operator instead
226
- fn check_is_none_or_err_and_early_return < ' tcx > ( & self , cx : & LateContext < ' tcx > , expr : & Expr < ' tcx > ) {
227
- if !self . inside_try_block ( )
228
- && let Some ( higher:: If { cond, then, r#else } ) = higher:: If :: hir ( expr)
229
- && !is_else_clause ( cx. tcx , expr)
230
- && let ExprKind :: MethodCall ( segment, caller, ..) = & cond. kind
231
- && let caller_ty = cx. typeck_results ( ) . expr_ty ( caller)
232
- && let if_block = IfBlockType :: IfIs ( caller, caller_ty, segment. ident . name , then)
233
- && ( is_early_return ( sym:: Option , cx, & if_block) || is_early_return ( sym:: Result , cx, & if_block) )
234
- {
235
- let mut applicability = Applicability :: MachineApplicable ;
236
- let receiver_str = snippet_with_applicability ( cx, caller. span , ".." , & mut applicability) ;
237
- let by_ref = !caller_ty. is_copy_modulo_regions ( cx. tcx , cx. param_env )
238
- && !matches ! ( caller. kind, ExprKind :: Call ( ..) | ExprKind :: MethodCall ( ..) ) ;
239
- let sugg = if let Some ( else_inner) = r#else {
240
- if eq_expr_value ( cx, caller, peel_blocks ( else_inner) ) {
241
- format ! ( "Some({receiver_str}?)" )
242
- } else {
243
- return ;
244
- }
206
+ /// Checks if the given expression on the given context matches the following structure:
207
+ ///
208
+ /// ```ignore
209
+ /// if option.is_none() {
210
+ /// return None;
211
+ /// }
212
+ /// ```
213
+ ///
214
+ /// ```ignore
215
+ /// if result.is_err() {
216
+ /// return result;
217
+ /// }
218
+ /// ```
219
+ ///
220
+ /// If it matches, it will suggest to use the question mark operator instead
221
+ fn check_is_none_or_err_and_early_return < ' tcx > ( cx : & LateContext < ' tcx > , expr : & Expr < ' tcx > ) {
222
+ if let Some ( higher:: If { cond, then, r#else } ) = higher:: If :: hir ( expr)
223
+ && !is_else_clause ( cx. tcx , expr)
224
+ && let ExprKind :: MethodCall ( segment, caller, ..) = & cond. kind
225
+ && let caller_ty = cx. typeck_results ( ) . expr_ty ( caller)
226
+ && let if_block = IfBlockType :: IfIs ( caller, caller_ty, segment. ident . name , then)
227
+ && ( is_early_return ( sym:: Option , cx, & if_block) || is_early_return ( sym:: Result , cx, & if_block) )
228
+ {
229
+ let mut applicability = Applicability :: MachineApplicable ;
230
+ let receiver_str = snippet_with_applicability ( cx, caller. span , ".." , & mut applicability) ;
231
+ let by_ref = !caller_ty. is_copy_modulo_regions ( cx. tcx , cx. param_env )
232
+ && !matches ! ( caller. kind, ExprKind :: Call ( ..) | ExprKind :: MethodCall ( ..) ) ;
233
+ let sugg = if let Some ( else_inner) = r#else {
234
+ if eq_expr_value ( cx, caller, peel_blocks ( else_inner) ) {
235
+ format ! ( "Some({receiver_str}?)" )
245
236
} else {
246
- format ! ( "{receiver_str}{}?;" , if by_ref { ".as_ref()" } else { "" } )
247
- } ;
237
+ return ;
238
+ }
239
+ } else {
240
+ format ! ( "{receiver_str}{}?;" , if by_ref { ".as_ref()" } else { "" } )
241
+ } ;
248
242
249
- span_lint_and_sugg (
250
- cx,
251
- QUESTION_MARK ,
252
- expr. span ,
253
- "this block may be rewritten with the `?` operator" ,
254
- "replace it with" ,
255
- sugg,
256
- applicability,
257
- ) ;
258
- }
243
+ span_lint_and_sugg (
244
+ cx,
245
+ QUESTION_MARK ,
246
+ expr. span ,
247
+ "this block may be rewritten with the `?` operator" ,
248
+ "replace it with" ,
249
+ sugg,
250
+ applicability,
251
+ ) ;
259
252
}
253
+ }
260
254
261
- fn check_if_let_some_or_err_and_early_return < ' tcx > ( & self , cx : & LateContext < ' tcx > , expr : & Expr < ' tcx > ) {
262
- if !self . inside_try_block ( )
263
- && let Some ( higher:: IfLet {
264
- let_pat,
265
- let_expr,
266
- if_then,
267
- if_else,
268
- ..
269
- } ) = higher:: IfLet :: hir ( cx, expr)
270
- && !is_else_clause ( cx. tcx , expr)
271
- && let PatKind :: TupleStruct ( ref path1, [ field] , ddpos) = let_pat. kind
272
- && ddpos. as_opt_usize ( ) . is_none ( )
273
- && let PatKind :: Binding ( BindingAnnotation ( by_ref, _) , bind_id, ident, None ) = field. kind
274
- && let caller_ty = cx. typeck_results ( ) . expr_ty ( let_expr)
275
- && let if_block = IfBlockType :: IfLet (
276
- cx. qpath_res ( path1, let_pat. hir_id ) ,
277
- caller_ty,
278
- ident. name ,
279
- let_expr,
280
- if_then,
281
- if_else,
282
- )
283
- && ( ( is_early_return ( sym:: Option , cx, & if_block) && path_to_local_id ( peel_blocks ( if_then) , bind_id) )
284
- || is_early_return ( sym:: Result , cx, & if_block) )
285
- && if_else
286
- . map ( |e| eq_expr_value ( cx, let_expr, peel_blocks ( e) ) )
287
- . filter ( |e| * e)
288
- . is_none ( )
289
- {
290
- let mut applicability = Applicability :: MachineApplicable ;
291
- let receiver_str = snippet_with_applicability ( cx, let_expr. span , ".." , & mut applicability) ;
292
- let requires_semi = matches ! ( cx. tcx. parent_hir_node( expr. hir_id) , Node :: Stmt ( _) ) ;
293
- let sugg = format ! (
294
- "{receiver_str}{}?{}" ,
295
- if by_ref == ByRef :: Yes { ".as_ref()" } else { "" } ,
296
- if requires_semi { ";" } else { "" }
297
- ) ;
298
- span_lint_and_sugg (
299
- cx,
300
- QUESTION_MARK ,
301
- expr. span ,
302
- "this block may be rewritten with the `?` operator" ,
303
- "replace it with" ,
304
- sugg,
305
- applicability,
306
- ) ;
307
- }
255
+ fn check_if_let_some_or_err_and_early_return < ' tcx > ( cx : & LateContext < ' tcx > , expr : & Expr < ' tcx > ) {
256
+ if let Some ( higher:: IfLet {
257
+ let_pat,
258
+ let_expr,
259
+ if_then,
260
+ if_else,
261
+ ..
262
+ } ) = higher:: IfLet :: hir ( cx, expr)
263
+ && !is_else_clause ( cx. tcx , expr)
264
+ && let PatKind :: TupleStruct ( ref path1, [ field] , ddpos) = let_pat. kind
265
+ && ddpos. as_opt_usize ( ) . is_none ( )
266
+ && let PatKind :: Binding ( BindingAnnotation ( by_ref, _) , bind_id, ident, None ) = field. kind
267
+ && let caller_ty = cx. typeck_results ( ) . expr_ty ( let_expr)
268
+ && let if_block = IfBlockType :: IfLet (
269
+ cx. qpath_res ( path1, let_pat. hir_id ) ,
270
+ caller_ty,
271
+ ident. name ,
272
+ let_expr,
273
+ if_then,
274
+ if_else,
275
+ )
276
+ && ( ( is_early_return ( sym:: Option , cx, & if_block) && path_to_local_id ( peel_blocks ( if_then) , bind_id) )
277
+ || is_early_return ( sym:: Result , cx, & if_block) )
278
+ && if_else
279
+ . map ( |e| eq_expr_value ( cx, let_expr, peel_blocks ( e) ) )
280
+ . filter ( |e| * e)
281
+ . is_none ( )
282
+ {
283
+ let mut applicability = Applicability :: MachineApplicable ;
284
+ let receiver_str = snippet_with_applicability ( cx, let_expr. span , ".." , & mut applicability) ;
285
+ let requires_semi = matches ! ( cx. tcx. parent_hir_node( expr. hir_id) , Node :: Stmt ( _) ) ;
286
+ let sugg = format ! (
287
+ "{receiver_str}{}?{}" ,
288
+ if by_ref == ByRef :: Yes { ".as_ref()" } else { "" } ,
289
+ if requires_semi { ";" } else { "" }
290
+ ) ;
291
+ span_lint_and_sugg (
292
+ cx,
293
+ QUESTION_MARK ,
294
+ expr. span ,
295
+ "this block may be rewritten with the `?` operator" ,
296
+ "replace it with" ,
297
+ sugg,
298
+ applicability,
299
+ ) ;
300
+ }
301
+ }
302
+
303
+ impl QuestionMark {
304
+ fn inside_try_block ( & self ) -> bool {
305
+ self . try_block_depth_stack . last ( ) > Some ( & 0 )
308
306
}
309
307
}
310
308
@@ -324,15 +322,18 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
324
322
return ;
325
323
}
326
324
327
- if !in_constant ( cx, stmt. hir_id ) {
325
+ if !self . inside_try_block ( ) && ! in_constant ( cx, stmt. hir_id ) {
328
326
check_let_some_else_return_none ( cx, stmt) ;
329
327
}
330
328
self . check_manual_let_else ( cx, stmt) ;
331
329
}
332
330
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
333
- if !in_constant ( cx, expr. hir_id ) && is_lint_allowed ( cx, QUESTION_MARK_USED , expr. hir_id ) {
334
- self . check_is_none_or_err_and_early_return ( cx, expr) ;
335
- self . check_if_let_some_or_err_and_early_return ( cx, expr) ;
331
+ if !self . inside_try_block ( )
332
+ && !in_constant ( cx, expr. hir_id )
333
+ && is_lint_allowed ( cx, QUESTION_MARK_USED , expr. hir_id )
334
+ {
335
+ check_is_none_or_err_and_early_return ( cx, expr) ;
336
+ check_if_let_some_or_err_and_early_return ( cx, expr) ;
336
337
}
337
338
}
338
339
0 commit comments