Skip to content

Commit 14d2afb

Browse files
committed
Merge pull request #711 from mcarton/hashmap
Fix false positive in `FOR_KV_MAP` and `&mut` refs
2 parents b3ffc18 + 62cbd87 commit 14d2afb

File tree

2 files changed

+16
-10
lines changed

2 files changed

+16
-10
lines changed

src/loops.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -588,24 +588,23 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex
588588
}
589589
}
590590

591-
// Check for the FOR_KV_MAP lint.
591+
/// Check for the FOR_KV_MAP lint.
592592
fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
593593
if let PatKind::Tup(ref pat) = pat.node {
594594
if pat.len() == 2 {
595-
596595
let (pat_span, kind) = match (&pat[0].node, &pat[1].node) {
597596
(key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"),
598597
(_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"),
599598
_ => return,
600599
};
601600

602-
let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg));
603-
let arg_span = if let ExprAddrOf(_, ref expr) = arg.node {
604-
expr.span
605-
} else {
606-
arg.span
601+
let arg_span = match arg.node {
602+
ExprAddrOf(MutImmutable, ref expr) => expr.span,
603+
ExprAddrOf(MutMutable, _) => return, // for _ in &mut _, there is no {values,keys}_mut method
604+
_ => arg.span,
607605
};
608606

607+
let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg));
609608
if match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &BTREEMAP_PATH) {
610609
span_lint_and_then(cx,
611610
FOR_KV_MAP,
@@ -625,7 +624,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
625624

626625
}
627626

628-
// Return true if the pattern is a `PatWild` or an ident prefixed with '_'.
627+
/// Return true if the pattern is a `PatWild` or an ident prefixed with '_'.
629628
fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
630629
match *pat {
631630
PatKind::Wild => true,
@@ -845,7 +844,7 @@ enum VarState {
845844
DontWarn,
846845
}
847846

848-
// Scan a for loop for variables that are incremented exactly once.
847+
/// Scan a for loop for variables that are incremented exactly once.
849848
struct IncrementVisitor<'v, 't: 'v> {
850849
cx: &'v LateContext<'v, 't>, // context reference
851850
states: HashMap<NodeId, VarState>, // incremented variables
@@ -897,7 +896,7 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> {
897896
}
898897
}
899898

900-
// Check whether a variable is initialized to zero at the start of a loop.
899+
/// Check whether a variable is initialized to zero at the start of a loop.
901900
struct InitializeVisitor<'v, 't: 'v> {
902901
cx: &'v LateContext<'v, 't>, // context reference
903902
end_expr: &'v Expr, // the for loop. Stop scanning here.

tests/compile-fail/for_loop.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,13 @@ fn main() {
311311
let _v = v;
312312
}
313313

314+
let mut m : HashMap<u64, u64> = HashMap::new();
315+
for (_, v) in &mut m {
316+
// Ok, there is no values_mut method or equivalent
317+
let _v = v;
318+
}
319+
320+
314321
let rm = &m;
315322
for (k, _value) in rm {
316323
//~^ you seem to want to iterate on a map's keys

0 commit comments

Comments
 (0)