@@ -59,80 +59,91 @@ declare_lint_pass!(LetIfSeq => [USELESS_LET_IF_SEQ]);
5959impl < ' tcx > LateLintPass < ' tcx > for LetIfSeq {
6060 fn check_block ( & mut self , cx : & LateContext < ' tcx > , block : & ' tcx hir:: Block < ' _ > ) {
6161 for [ stmt, next] in block. stmts . array_windows :: < 2 > ( ) {
62- if let hir:: StmtKind :: Let ( local) = stmt. kind
63- && let hir:: PatKind :: Binding ( mode, canonical_id, ident, None ) = local. pat . kind
64- && let hir:: StmtKind :: Expr ( if_) = next. kind
65- && let hir:: ExprKind :: If ( cond, then, else_) = if_. kind
66- && !is_local_used ( cx, cond, canonical_id)
67- && let hir:: ExprKind :: Block ( then, _) = then. kind
68- && let Some ( value) = check_assign ( cx, canonical_id, then)
69- && !is_local_used ( cx, value, canonical_id)
70- {
71- let span = stmt. span . to ( if_. span ) ;
62+ if let hir:: StmtKind :: Expr ( if_) = next. kind {
63+ check_block_inner ( cx, stmt, if_) ;
64+ }
65+ }
7266
73- let has_interior_mutability = !cx
74- . typeck_results ( )
75- . node_type ( canonical_id)
76- . is_freeze ( cx. tcx , cx. typing_env ( ) ) ;
77- if has_interior_mutability {
78- return ;
79- }
67+ if let Some ( expr) = block. expr
68+ && let Some ( stmt) = block. stmts . last ( )
69+ {
70+ check_block_inner ( cx, stmt, expr) ;
71+ }
72+ }
73+ }
74+
75+ fn check_block_inner < ' tcx > ( cx : & LateContext < ' tcx > , stmt : & ' tcx hir:: Stmt < ' tcx > , if_ : & ' tcx hir:: Expr < ' tcx > ) {
76+ if let hir:: StmtKind :: Let ( local) = stmt. kind
77+ && let hir:: PatKind :: Binding ( mode, canonical_id, ident, None ) = local. pat . kind
78+ && let hir:: ExprKind :: If ( cond, then, else_) = if_. kind
79+ && !is_local_used ( cx, cond, canonical_id)
80+ && let hir:: ExprKind :: Block ( then, _) = then. kind
81+ && let Some ( value) = check_assign ( cx, canonical_id, then)
82+ && !is_local_used ( cx, value, canonical_id)
83+ {
84+ let span = stmt. span . to ( if_. span ) ;
8085
81- let ( default_multi_stmts , default ) = if let Some ( else_ ) = else_ {
82- if let hir :: ExprKind :: Block ( else_ , _ ) = else_ . kind {
83- if let Some ( default ) = check_assign ( cx , canonical_id, else_ ) {
84- ( else_ . stmts . len ( ) > 1 , default )
85- } else if let Some ( default ) = local . init {
86- ( true , default )
87- } else {
88- continue ;
89- }
90- } else {
91- continue ;
92- }
86+ let has_interior_mutability = !cx
87+ . typeck_results ( )
88+ . node_type ( canonical_id)
89+ . is_freeze ( cx . tcx , cx . typing_env ( ) ) ;
90+ if has_interior_mutability {
91+ return ;
92+ }
93+
94+ let ( default_multi_stmts , default ) = if let Some ( else_ ) = else_ {
95+ if let hir :: ExprKind :: Block ( else_ , _ ) = else_ . kind {
96+ if let Some ( default ) = check_assign ( cx , canonical_id , else_ ) {
97+ ( else_ . stmts . len ( ) > 1 , default )
9398 } else if let Some ( default) = local. init {
94- ( false , default)
99+ ( true , default)
95100 } else {
96- continue ;
97- } ;
101+ return ;
102+ }
103+ } else {
104+ return ;
105+ }
106+ } else if let Some ( default) = local. init {
107+ ( false , default)
108+ } else {
109+ return ;
110+ } ;
98111
99- let mutability = match mode {
100- BindingMode ( _, Mutability :: Mut ) => "<mut> " ,
101- _ => "" ,
102- } ;
112+ let mutability = match mode {
113+ BindingMode ( _, Mutability :: Mut ) => "<mut> " ,
114+ _ => "" ,
115+ } ;
103116
104- // FIXME: this should not suggest `mut` if we can detect that the variable is not
105- // use mutably after the `if`
117+ // FIXME: this should not suggest `mut` if we can detect that the variable is not
118+ // use mutably after the `if`
106119
107- let sug = format ! (
108- "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};" ,
109- name=ident. name,
110- cond=snippet( cx, cond. span, "_" ) ,
111- then=if then. stmts. len( ) > 1 { " ..;" } else { "" } ,
112- else=if default_multi_stmts { " ..;" } else { "" } ,
113- value=snippet( cx, value. span, "<value>" ) ,
114- default =snippet( cx, default . span, "<default>" ) ,
115- ) ;
116- span_lint_hir_and_then (
117- cx,
118- USELESS_LET_IF_SEQ ,
119- local. hir_id ,
120+ let sug = format ! (
121+ "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};" ,
122+ name=ident. name,
123+ cond=snippet( cx, cond. span, "_" ) ,
124+ then=if then. stmts. len( ) > 1 { " ..;" } else { "" } ,
125+ else=if default_multi_stmts { " ..;" } else { "" } ,
126+ value=snippet( cx, value. span, "<value>" ) ,
127+ default =snippet( cx, default . span, "<default>" ) ,
128+ ) ;
129+ span_lint_hir_and_then (
130+ cx,
131+ USELESS_LET_IF_SEQ ,
132+ local. hir_id ,
133+ span,
134+ "`if _ { .. } else { .. }` is an expression" ,
135+ |diag| {
136+ diag. span_suggestion (
120137 span,
121- "`if _ { .. } else { .. }` is an expression" ,
122- |diag| {
123- diag. span_suggestion (
124- span,
125- "it is more idiomatic to write" ,
126- sug,
127- Applicability :: HasPlaceholders ,
128- ) ;
129- if !mutability. is_empty ( ) {
130- diag. note ( "you might not need `mut` at all" ) ;
131- }
132- } ,
138+ "it is more idiomatic to write" ,
139+ sug,
140+ Applicability :: HasPlaceholders ,
133141 ) ;
134- }
135- }
142+ if !mutability. is_empty ( ) {
143+ diag. note ( "you might not need `mut` at all" ) ;
144+ }
145+ } ,
146+ ) ;
136147 }
137148}
138149
0 commit comments