@@ -196,13 +196,25 @@ fn collect_unwrap_info<'tcx>(
196
196
}
197
197
198
198
/// A HIR visitor delegate that checks if a local variable of type `Option<_>` is mutated,
199
- /// unless `Option::as_mut` is called.
199
+ /// *except* for if `Option::as_mut` is called.
200
+ /// The reason for why we allow that one specifically is that `.as_mut()` cannot change
201
+ /// the option to `None`, and that is important because this lint relies on the fact that
202
+ /// `is_some` + `unwrap` is equivalent to `if let Some(..) = ..`, which it would not be if
203
+ /// the option is changed to None between `is_some` and `unwrap`.
204
+ /// (And also `.as_mut()` is a somewhat common method that is still worth linting on.)
200
205
struct MutationVisitor < ' tcx > {
201
206
is_mutated : bool ,
202
207
local_id : HirId ,
203
208
tcx : TyCtxt < ' tcx > ,
204
209
}
205
210
211
+ /// Checks if the parent of the expression pointed at by the given `HirId` is a call to
212
+ /// `Option::as_mut`.
213
+ ///
214
+ /// Used by the mutation visitor to specifically allow `.as_mut()` calls.
215
+ /// In particular, the `HirId` that the visitor receives is the id of the local expression
216
+ /// (i.e. the `x` in `x.as_mut()`), and that is the reason for why we care about its parent
217
+ /// expression: that will be where the actual method call is.
206
218
fn is_option_as_mut_use ( tcx : TyCtxt < ' _ > , expr_id : HirId ) -> bool {
207
219
if let Node :: Expr ( mutating_expr) = tcx. hir ( ) . get_parent ( expr_id)
208
220
&& let ExprKind :: MethodCall ( path, ..) = mutating_expr. kind
@@ -260,7 +272,8 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
260
272
vis. walk_expr ( branch) ;
261
273
262
274
if delegate. is_mutated {
263
- // if the variable is mutated, we don't know whether it can be unwrapped:
275
+ // if the variable is mutated, we don't know whether it can be unwrapped.
276
+ // it might have been changed to `None` in between `is_some` + `unwrap`.
264
277
continue ;
265
278
}
266
279
self . unwrappables . push ( unwrap_info) ;
0 commit comments