Skip to content

Commit b66dbe8

Browse files
committed
Auto merge of rust-lang#8228 - Jarcho:iter_not_returning_iterator_8225, r=giraffate
fix `iter_not_returning_iterator` fixes rust-lang#8225 changelog: Handle type projections in `iter_not_returning_iterator` changelog: Don't lint `iter_not_returning_iterator` in trait implementations changelog: Lint `iter_not_returning_iterator` in trait definitions
2 parents 1816361 + d98339d commit b66dbe8

File tree

3 files changed

+72
-21
lines changed

3 files changed

+72
-21
lines changed

clippy_lints/src/iter_not_returning_iterator.rs

+45-20
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
use clippy_utils::{diagnostics::span_lint, return_ty, ty::implements_trait};
2-
use rustc_hir::{ImplItem, ImplItemKind};
1+
use clippy_utils::{diagnostics::span_lint, get_parent_node, ty::implements_trait};
2+
use rustc_hir::{def_id::LocalDefId, FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind};
33
use rustc_lint::{LateContext, LateLintPass};
44
use rustc_session::{declare_lint_pass, declare_tool_lint};
5-
use rustc_span::symbol::kw;
65
use rustc_span::symbol::sym;
76

87
declare_clippy_lint! {
@@ -41,25 +40,51 @@ declare_clippy_lint! {
4140
declare_lint_pass!(IterNotReturningIterator => [ITER_NOT_RETURNING_ITERATOR]);
4241

4342
impl LateLintPass<'_> for IterNotReturningIterator {
44-
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'tcx>) {
45-
let name = impl_item.ident.name.as_str();
46-
if_chain! {
47-
if let ImplItemKind::Fn(fn_sig, _) = &impl_item.kind;
48-
let ret_ty = return_ty(cx, impl_item.hir_id());
49-
if matches!(name, "iter" | "iter_mut");
50-
if let [param] = cx.tcx.fn_arg_names(impl_item.def_id);
51-
if param.name == kw::SelfLower;
52-
if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
53-
if !implements_trait(cx, ret_ty, iter_trait_id, &[]);
43+
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
44+
let name = item.ident.name.as_str();
45+
if matches!(name, "iter" | "iter_mut") {
46+
if let TraitItemKind::Fn(fn_sig, _) = &item.kind {
47+
check_sig(cx, name, fn_sig, item.def_id);
48+
}
49+
}
50+
}
5451

55-
then {
56-
span_lint(
57-
cx,
58-
ITER_NOT_RETURNING_ITERATOR,
59-
fn_sig.span,
60-
&format!("this method is named `{}` but its return type does not implement `Iterator`", name),
61-
);
52+
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
53+
let name = item.ident.name.as_str();
54+
if matches!(name, "iter" | "iter_mut")
55+
&& !matches!(
56+
get_parent_node(cx.tcx, item.hir_id()),
57+
Some(Node::Item(Item { kind: ItemKind::Impl(i), .. })) if i.of_trait.is_some()
58+
)
59+
{
60+
if let ImplItemKind::Fn(fn_sig, _) = &item.kind {
61+
check_sig(cx, name, fn_sig, item.def_id);
6262
}
6363
}
6464
}
6565
}
66+
67+
fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefId) {
68+
if sig.decl.implicit_self.has_implicit_self() {
69+
let ret_ty = cx.tcx.fn_sig(fn_id).skip_binder().output();
70+
let ret_ty = cx
71+
.tcx
72+
.try_normalize_erasing_regions(cx.param_env, ret_ty)
73+
.unwrap_or(ret_ty);
74+
if cx
75+
.tcx
76+
.get_diagnostic_item(sym::Iterator)
77+
.map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[]))
78+
{
79+
span_lint(
80+
cx,
81+
ITER_NOT_RETURNING_ITERATOR,
82+
sig.span,
83+
&format!(
84+
"this method is named `{}` but its return type does not implement `Iterator`",
85+
name
86+
),
87+
);
88+
}
89+
}
90+
}

tests/ui/iter_not_returning_iterator.rs

+20
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,24 @@ impl Iterator for Counter {
4444
}
4545
}
4646

47+
// Issue #8225
48+
trait Iter {
49+
type I;
50+
fn iter(&self) -> Self::I;
51+
}
52+
53+
impl Iter for () {
54+
type I = core::slice::Iter<'static, ()>;
55+
fn iter(&self) -> Self::I {
56+
[].iter()
57+
}
58+
}
59+
60+
struct S;
61+
impl S {
62+
fn iter(&self) -> <() as Iter>::I {
63+
().iter()
64+
}
65+
}
66+
4767
fn main() {}

tests/ui/iter_not_returning_iterator.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,11 @@ error: this method is named `iter_mut` but its return type does not implement `I
1212
LL | fn iter_mut(&self) -> Counter2 {
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

15-
error: aborting due to 2 previous errors
15+
error: this method is named `iter` but its return type does not implement `Iterator`
16+
--> $DIR/iter_not_returning_iterator.rs:50:5
17+
|
18+
LL | fn iter(&self) -> Self::I;
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 3 previous errors
1622

0 commit comments

Comments
 (0)