@@ -2150,8 +2150,20 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b
2150
2150
return ;
2151
2151
}
2152
2152
2153
+ if mut_var_visitor. ids . is_empty ( ) {
2154
+ span_lint (
2155
+ cx,
2156
+ WHILE_IMMUTABLE_CONDITION ,
2157
+ cond. span ,
2158
+ "all variables in condition are immutable. This either leads to an infinite or to a never running loop." ,
2159
+ ) ;
2160
+ return ;
2161
+ }
2162
+
2163
+
2153
2164
let mut delegate = MutVarsDelegate {
2154
2165
used_mutably : mut_var_visitor. ids ,
2166
+ skip : false ,
2155
2167
} ;
2156
2168
let def_id = def_id:: DefId :: local ( block. hir_id . owner ) ;
2157
2169
let region_scope_tree = & cx. tcx . region_scope_tree ( def_id) ;
@@ -2194,7 +2206,10 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
2194
2206
impl < ' a , ' tcx > Visitor < ' tcx > for VarCollectorVisitor < ' a , ' tcx > {
2195
2207
fn visit_expr ( & mut self , ex : & ' tcx Expr ) {
2196
2208
match ex. node {
2197
- ExprPath ( _) => self . insert_def_id ( ex) ,
2209
+ ExprPath ( _) => if let Some ( node_id) = check_for_mutability ( self . cx , ex) {
2210
+ self . ids . insert ( node_id, false ) ;
2211
+ } ,
2212
+
2198
2213
// If there is any fuction/method call… we just stop analysis
2199
2214
ExprCall ( ..) | ExprMethodCall ( ..) => self . skip = true ,
2200
2215
@@ -2211,6 +2226,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
2211
2226
2212
2227
struct MutVarsDelegate {
2213
2228
used_mutably : HashMap < NodeId , bool > ,
2229
+ skip : bool ,
2214
2230
}
2215
2231
2216
2232
impl < ' tcx > MutVarsDelegate {
@@ -2220,6 +2236,7 @@ impl<'tcx> MutVarsDelegate {
2220
2236
if let Some ( used) = self . used_mutably . get_mut ( & id) {
2221
2237
* used = true ;
2222
2238
} ,
2239
+ Categorization :: Upvar ( _) => skip = true ,
2223
2240
Categorization :: Deref ( ref cmt, _) => self . update ( & cmt. cat , sp) ,
2224
2241
_ => { }
2225
2242
}
0 commit comments