From 0217fb81ee80776899440f997a8b71212dbfe17a Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 31 Aug 2015 08:29:34 +0200 Subject: [PATCH] loops: fix false positives with explicit_iter_loop and references (fixes #261) --- src/loops.rs | 6 ++++-- tests/compile-fail/for_loop.rs | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/loops.rs b/src/loops.rs index f6247dd8419e..33401dc67e12 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -4,7 +4,7 @@ use syntax::visit::{Visitor, walk_expr}; use rustc::middle::ty; use std::collections::HashSet; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, walk_ptrs_ty, +use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, expr_block, span_help_and_lint}; use utils::{VEC_PATH, LL_PATH}; @@ -191,7 +191,9 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { /// Return true if the type of expr is one that provides IntoIterator impls /// for &T and &mut T, such as Vec. fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool { - let ty = walk_ptrs_ty(cx.tcx.expr_ty(e)); + // no walk_ptrs_ty: calling iter() on a reference can make sense because it + // will allow further borrows afterwards + let ty = cx.tcx.expr_ty(e); is_array(ty) || match_type(cx, ty, &VEC_PATH) || match_type(cx, ty, &LL_PATH) || diff --git a/tests/compile-fail/for_loop.rs b/tests/compile-fail/for_loop.rs index 668386513561..f2540bfd5952 100755 --- a/tests/compile-fail/for_loop.rs +++ b/tests/compile-fail/for_loop.rs @@ -37,6 +37,7 @@ fn main() { for _v in &mut vec { } // these are fine for _v in [1, 2, 3].iter() { } //~ERROR it is more idiomatic to loop over `&[ + for _v in (&mut [1, 2, 3]).iter() { } // no error let ll: LinkedList<()> = LinkedList::new(); for _v in ll.iter() { } //~ERROR it is more idiomatic to loop over `&ll` let vd: VecDeque<()> = VecDeque::new();