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}
;
3 use rustc_lint
::{LateContext, LateLintPass}
;
4 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
5 use rustc_span
::symbol
::sym
;
9 /// Detects methods named `iter` or `iter_mut` that do not have a return type that implements `Iterator`.
11 /// ### Why is this bad?
12 /// Methods named `iter` or `iter_mut` conventionally return an `Iterator`.
16 /// // `String` does not implement `Iterator`
19 /// fn iter(&self) -> String {
26 /// use std::str::Chars;
29 /// fn iter(&self) -> Chars<'static> {
34 #[clippy::version = "1.57.0"]
35 pub ITER_NOT_RETURNING_ITERATOR
,
37 "methods named `iter` or `iter_mut` that do not return an `Iterator`"
40 declare_lint_pass
!(IterNotReturningIterator
=> [ITER_NOT_RETURNING_ITERATOR
]);
42 impl<'tcx
> LateLintPass
<'tcx
> for IterNotReturningIterator
{
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
.owner_id
.def_id
);
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")
56 get_parent_node(cx
.tcx
, item
.hir_id()),
57 Some(Node
::Item(Item { kind: ItemKind::Impl(i), .. }
)) if i
.of_trait
.is_some()
60 if let ImplItemKind
::Fn(fn_sig
, _
) = &item
.kind
{
61 check_sig(cx
, name
, fn_sig
, item
.owner_id
.def_id
);
67 fn check_sig(cx
: &LateContext
<'_
>, name
: &str, sig
: &FnSig
<'_
>, fn_id
: LocalDefId
) {
68 if sig
.decl
.implicit_self
.has_implicit_self() {
71 .erase_late_bound_regions(cx
.tcx
.fn_sig(fn_id
).subst_identity().output());
74 .try_normalize_erasing_regions(cx
.param_env
, ret_ty
)
78 .get_diagnostic_item(sym
::Iterator
)
79 .map_or(false, |iter_id
| !implements_trait(cx
, ret_ty
, iter_id
, &[]))
83 ITER_NOT_RETURNING_ITERATOR
,
85 &format
!("this method is named `{name}` but its return type does not implement `Iterator`"),