1
1
use clippy_utils:: diagnostics:: { span_lint, span_lint_and_note} ;
2
2
use clippy_utils:: { get_parent_expr, path_to_local, path_to_local_id} ;
3
3
use if_chain:: if_chain;
4
- use rustc_hir:: intravisit:: { walk_block , walk_expr, Visitor } ;
4
+ use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
5
5
use rustc_hir:: { BinOpKind , Block , Expr , ExprKind , Guard , HirId , Local , Node , Stmt , StmtKind } ;
6
6
use rustc_lint:: { LateContext , LateLintPass } ;
7
7
use rustc_middle:: ty;
@@ -114,7 +114,7 @@ struct DivergenceVisitor<'a, 'tcx> {
114
114
impl < ' a , ' tcx > DivergenceVisitor < ' a , ' tcx > {
115
115
fn maybe_walk_expr ( & mut self , e : & ' tcx Expr < ' _ > ) {
116
116
match e. kind {
117
- ExprKind :: Closure { .. } => { } ,
117
+ ExprKind :: Closure ( .. ) | ExprKind :: If ( .. ) | ExprKind :: Loop ( .. ) => { } ,
118
118
ExprKind :: Match ( e, arms, _) => {
119
119
self . visit_expr ( e) ;
120
120
for arm in arms {
@@ -128,6 +128,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
128
128
_ => walk_expr ( self , e) ,
129
129
}
130
130
}
131
+
131
132
fn report_diverging_sub_expr ( & mut self , e : & Expr < ' _ > ) {
132
133
span_lint ( self . cx , DIVERGING_SUB_EXPRESSION , e. span , "sub-expression diverges" ) ;
133
134
}
@@ -136,6 +137,15 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
136
137
impl < ' a , ' tcx > Visitor < ' tcx > for DivergenceVisitor < ' a , ' tcx > {
137
138
fn visit_expr ( & mut self , e : & ' tcx Expr < ' _ > ) {
138
139
match e. kind {
140
+ // fix #10776
141
+ ExprKind :: Block ( block, ..) => {
142
+ if let Some ( stmt) = block. stmts . first ( ) && block. stmts . len ( ) == 1 {
143
+ match stmt. kind {
144
+ StmtKind :: Expr ( e) | StmtKind :: Semi ( e) => self . visit_expr ( e) ,
145
+ _ => { } ,
146
+ }
147
+ }
148
+ } ,
139
149
ExprKind :: Continue ( _) | ExprKind :: Break ( _, _) | ExprKind :: Ret ( _) => self . report_diverging_sub_expr ( e) ,
140
150
ExprKind :: Call ( func, _) => {
141
151
let typ = self . cx . typeck_results ( ) . expr_ty ( func) ;
@@ -155,7 +165,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
155
165
self . report_diverging_sub_expr ( e) ;
156
166
}
157
167
} ,
158
- ExprKind :: Block ( block, ..) => walk_block ( self , block) ,
159
168
_ => {
160
169
// do not lint expressions referencing objects of type `!`, as that required a
161
170
// diverging expression
@@ -164,6 +173,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
164
173
}
165
174
self . maybe_walk_expr ( e) ;
166
175
}
176
+ fn visit_block ( & mut self , _: & ' tcx Block < ' _ > ) {
177
+ // don't continue over blocks, LateLintPass already does that
178
+ }
167
179
}
168
180
169
181
/// Walks up the AST from the given write expression (`vis.write_expr`) looking
0 commit comments