@@ -17,7 +17,7 @@ use if_chain::if_chain;
1717
1818use crate :: rustc_errors:: Applicability ;
1919use crate :: utils:: paths:: * ;
20- use crate :: utils:: { match_def_path, match_type, span_lint_and_then} ;
20+ use crate :: utils:: { match_def_path, match_type, span_lint_and_then, SpanlessEq } ;
2121
2222/// **What it does:** Checks for expressions that could be replaced by the question mark operator
2323///
@@ -64,14 +64,40 @@ impl Pass {
6464 /// If it matches, it will suggest to use the question mark operator instead
6565 fn check_is_none_and_early_return_none ( cx : & LateContext < ' _ , ' _ > , expr : & Expr ) {
6666 if_chain ! {
67- if let ExprKind :: If ( ref if_expr, ref body, _ ) = expr. node;
68- if let ExprKind :: MethodCall ( ref segment, _, ref args) = if_expr. node;
67+ if let ExprKind :: If ( if_expr, body, else_ ) = & expr. node;
68+ if let ExprKind :: MethodCall ( segment, _, args) = & if_expr. node;
6969 if segment. ident. name == "is_none" ;
7070 if Self :: expression_returns_none( cx, body) ;
7171 if let Some ( subject) = args. get( 0 ) ;
7272 if Self :: is_option( cx, subject) ;
7373
7474 then {
75+ if let Some ( else_) = else_ {
76+ if_chain! {
77+ if let ExprKind :: Block ( block, None ) = & else_. node;
78+ if block. stmts. len( ) == 0 ;
79+ if let Some ( block_expr) = & block. expr;
80+ if SpanlessEq :: new( cx) . ignore_fn( ) . eq_expr( subject, block_expr) ;
81+ then {
82+ span_lint_and_then(
83+ cx,
84+ QUESTION_MARK ,
85+ expr. span,
86+ "this block may be rewritten with the `?` operator" ,
87+ |db| {
88+ db. span_suggestion_with_applicability(
89+ expr. span,
90+ "replace_it_with" ,
91+ format!( "Some({}?)" , Sugg :: hir( cx, subject, ".." ) ) ,
92+ Applicability :: MaybeIncorrect , // snippet
93+ ) ;
94+ }
95+ )
96+ }
97+ }
98+ return ;
99+ }
100+
75101 span_lint_and_then(
76102 cx,
77103 QUESTION_MARK ,
@@ -84,7 +110,7 @@ impl Pass {
84110 expr. span,
85111 "replace_it_with" ,
86112 format!( "{}?;" , receiver_str) ,
87- Applicability :: MachineApplicable , // snippet
113+ Applicability :: MaybeIncorrect , // snippet
88114 ) ;
89115 }
90116 )
@@ -133,9 +159,13 @@ impl Pass {
133159 }
134160 }
135161
136- // Check if the block has an implicit return expression
137- if let Some ( ref ret_expr) = block. expr {
138- return Some ( ret_expr. clone ( ) ) ;
162+ // Check for `return` without a semicolon.
163+ if_chain ! {
164+ if block. stmts. len( ) == 0 ;
165+ if let Some ( ExprKind :: Ret ( Some ( ret_expr) ) ) = block. expr. as_ref( ) . map( |e| & e. node) ;
166+ then {
167+ return Some ( ret_expr. clone( ) ) ;
168+ }
139169 }
140170
141171 None
0 commit comments