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.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.def_id);
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.erase_late_bound_regions(cx.tcx.fn_sig(fn_id).output());
72 .try_normalize_erasing_regions(cx.param_env, ret_ty)
76 .get_diagnostic_item(sym::Iterator)
77 .map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[]))
81 ITER_NOT_RETURNING_ITERATOR,
84 "this method is named `{}` but its return type does not implement `Iterator`",