Skip to content

Commit 304edf3

Browse files
committed
Auto merge of #4978 - mikerite:fix-4958, r=phansch
Fix bad `explicit_into_iter_loop` suggestion Fixes #4958 changelog: Fix bad `explicit_into_iter_loop` suggestion
2 parents 5b710ee + ea829bd commit 304edf3

File tree

4 files changed

+108
-17
lines changed

4 files changed

+108
-17
lines changed

clippy_lints/src/loops.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ use rustc_session::declare_tool_lint;
1212
// use rustc::middle::region::CodeExtent;
1313
use crate::consts::{constant, Constant};
1414
use crate::utils::usage::mutated_variables;
15-
use crate::utils::{is_type_diagnostic_item, qpath_res, sext, sugg};
16-
use rustc::ty::subst::Subst;
15+
use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg};
1716
use rustc::ty::{self, Ty};
1817
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1918
use rustc_errors::Applicability;
@@ -1344,20 +1343,9 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e
13441343
lint_iter_method(cx, args, arg, method_name);
13451344
}
13461345
} else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) {
1347-
let def_id = cx.tables.type_dependent_def_id(arg.hir_id).unwrap();
1348-
let substs = cx.tables.node_substs(arg.hir_id);
1349-
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
1350-
1351-
let fn_arg_tys = method_type.fn_sig(cx.tcx).inputs();
1352-
assert_eq!(fn_arg_tys.skip_binder().len(), 1);
1353-
if fn_arg_tys.skip_binder()[0].is_region_ptr() {
1354-
match cx.tables.expr_ty(&args[0]).kind {
1355-
// If the length is greater than 32 no traits are implemented for array and
1356-
// therefore we cannot use `&`.
1357-
ty::Array(_, size) if size.eval_usize(cx.tcx, cx.param_env) > 32 => {},
1358-
_ => lint_iter_method(cx, args, arg, method_name),
1359-
};
1360-
} else {
1346+
let receiver_ty = cx.tables.expr_ty(&args[0]);
1347+
let receiver_ty_adjusted = cx.tables.expr_ty_adjusted(&args[0]);
1348+
if same_tys(cx, receiver_ty, receiver_ty_adjusted) {
13611349
let mut applicability = Applicability::MachineApplicable;
13621350
let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
13631351
span_lint_and_sugg(
@@ -1370,6 +1358,17 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e
13701358
object.to_string(),
13711359
applicability,
13721360
);
1361+
} else {
1362+
let ref_receiver_ty = cx.tcx.mk_ref(
1363+
cx.tcx.lifetimes.re_erased,
1364+
ty::TypeAndMut {
1365+
ty: receiver_ty,
1366+
mutbl: Mutability::Not,
1367+
},
1368+
);
1369+
if same_tys(cx, receiver_ty_adjusted, ref_receiver_ty) {
1370+
lint_iter_method(cx, args, arg, method_name)
1371+
}
13731372
}
13741373
} else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) {
13751374
span_lint(

tests/ui/for_loop_fixable.fixed

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,40 @@ mod issue_2496 {
299299
unimplemented!()
300300
}
301301
}
302+
303+
// explicit_into_iter_loop bad suggestions
304+
#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)]
305+
mod issue_4958 {
306+
fn takes_iterator<T>(iterator: &T)
307+
where
308+
for<'a> &'a T: IntoIterator<Item = &'a String>,
309+
{
310+
for i in iterator {
311+
println!("{}", i);
312+
}
313+
}
314+
315+
struct T;
316+
impl IntoIterator for &T {
317+
type Item = ();
318+
type IntoIter = std::vec::IntoIter<Self::Item>;
319+
fn into_iter(self) -> Self::IntoIter {
320+
vec![].into_iter()
321+
}
322+
}
323+
324+
fn more_tests() {
325+
let t = T;
326+
let r = &t;
327+
let rr = &&t;
328+
329+
// This case is handled by `explicit_iter_loop`. No idea why.
330+
for _ in &t {}
331+
332+
for _ in r {}
333+
334+
// No suggestion for this.
335+
// We'd have to suggest `for _ in *rr {}` which is less clear.
336+
for _ in rr.into_iter() {}
337+
}
338+
}

tests/ui/for_loop_fixable.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,40 @@ mod issue_2496 {
299299
unimplemented!()
300300
}
301301
}
302+
303+
// explicit_into_iter_loop bad suggestions
304+
#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)]
305+
mod issue_4958 {
306+
fn takes_iterator<T>(iterator: &T)
307+
where
308+
for<'a> &'a T: IntoIterator<Item = &'a String>,
309+
{
310+
for i in iterator.into_iter() {
311+
println!("{}", i);
312+
}
313+
}
314+
315+
struct T;
316+
impl IntoIterator for &T {
317+
type Item = ();
318+
type IntoIter = std::vec::IntoIter<Self::Item>;
319+
fn into_iter(self) -> Self::IntoIter {
320+
vec![].into_iter()
321+
}
322+
}
323+
324+
fn more_tests() {
325+
let t = T;
326+
let r = &t;
327+
let rr = &&t;
328+
329+
// This case is handled by `explicit_iter_loop`. No idea why.
330+
for _ in t.into_iter() {}
331+
332+
for _ in r.into_iter() {}
333+
334+
// No suggestion for this.
335+
// We'd have to suggest `for _ in *rr {}` which is less clear.
336+
for _ in rr.into_iter() {}
337+
}
338+
}

tests/ui/for_loop_fixable.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,23 @@ error: it is more concise to loop over references to containers instead of using
130130
LL | for _v in bs.iter() {}
131131
| ^^^^^^^^^ help: to write this more concisely, try: `&bs`
132132

133-
error: aborting due to 17 previous errors
133+
error: it is more concise to loop over containers instead of using explicit iteration methods`
134+
--> $DIR/for_loop_fixable.rs:310:18
135+
|
136+
LL | for i in iterator.into_iter() {
137+
| ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator`
138+
139+
error: it is more concise to loop over references to containers instead of using explicit iteration methods
140+
--> $DIR/for_loop_fixable.rs:330:18
141+
|
142+
LL | for _ in t.into_iter() {}
143+
| ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t`
144+
145+
error: it is more concise to loop over containers instead of using explicit iteration methods`
146+
--> $DIR/for_loop_fixable.rs:332:18
147+
|
148+
LL | for _ in r.into_iter() {}
149+
| ^^^^^^^^^^^^^ help: to write this more concisely, try: `r`
150+
151+
error: aborting due to 20 previous errors
134152

0 commit comments

Comments
 (0)