11use clippy_utils:: diagnostics:: { span_lint, span_lint_and_note} ;
22use clippy_utils:: { get_parent_expr, path_to_local, path_to_local_id} ;
33use if_chain:: if_chain;
4- use rustc_hir:: intravisit:: { walk_block , walk_expr, Visitor } ;
4+ use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
55use rustc_hir:: { BinOpKind , Block , Expr , ExprKind , Guard , HirId , Local , Node , Stmt , StmtKind } ;
66use rustc_lint:: { LateContext , LateLintPass } ;
77use rustc_middle:: ty;
@@ -114,7 +114,7 @@ struct DivergenceVisitor<'a, 'tcx> {
114114impl < ' a , ' tcx > DivergenceVisitor < ' a , ' tcx > {
115115 fn maybe_walk_expr ( & mut self , e : & ' tcx Expr < ' _ > ) {
116116 match e. kind {
117- ExprKind :: Closure { .. } => { } ,
117+ ExprKind :: Closure ( .. ) | ExprKind :: If ( .. ) | ExprKind :: Loop ( .. ) => { } ,
118118 ExprKind :: Match ( e, arms, _) => {
119119 self . visit_expr ( e) ;
120120 for arm in arms {
@@ -128,6 +128,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
128128 _ => walk_expr ( self , e) ,
129129 }
130130 }
131+
131132 fn report_diverging_sub_expr ( & mut self , e : & Expr < ' _ > ) {
132133 span_lint ( self . cx , DIVERGING_SUB_EXPRESSION , e. span , "sub-expression diverges" ) ;
133134 }
@@ -136,6 +137,15 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
136137impl < ' a , ' tcx > Visitor < ' tcx > for DivergenceVisitor < ' a , ' tcx > {
137138 fn visit_expr ( & mut self , e : & ' tcx Expr < ' _ > ) {
138139 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+ } ,
139149 ExprKind :: Continue ( _) | ExprKind :: Break ( _, _) | ExprKind :: Ret ( _) => self . report_diverging_sub_expr ( e) ,
140150 ExprKind :: Call ( func, _) => {
141151 let typ = self . cx . typeck_results ( ) . expr_ty ( func) ;
@@ -155,7 +165,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
155165 self . report_diverging_sub_expr ( e) ;
156166 }
157167 } ,
158- ExprKind :: Block ( block, ..) => walk_block ( self , block) ,
159168 _ => {
160169 // do not lint expressions referencing objects of type `!`, as that required a
161170 // diverging expression
@@ -164,6 +173,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
164173 }
165174 self . maybe_walk_expr ( e) ;
166175 }
176+ fn visit_block ( & mut self , _: & ' tcx Block < ' _ > ) {
177+ // don't continue over blocks, LateLintPass already does that
178+ }
167179}
168180
169181/// Walks up the AST from the given write expression (`vis.write_expr`) looking
0 commit comments