]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
Rollup merge of #89789 - jkugelman:must-use-thread-builder, r=joshtriplett
[rust.git] / src / tools / clippy / clippy_lints / src / iter_not_returning_iterator.rs
1 use clippy_utils::{diagnostics::span_lint, return_ty, ty::implements_trait};
2 use rustc_hir::{ImplItem, ImplItemKind};
3 use rustc_lint::{LateContext, LateLintPass};
4 use rustc_session::{declare_lint_pass, declare_tool_lint};
5 use rustc_span::symbol::kw;
6 use rustc_span::symbol::sym;
7
8 declare_clippy_lint! {
9     /// ### What it does
10     /// Detects methods named `iter` or `iter_mut` that do not have a return type that implements `Iterator`.
11     ///
12     /// ### Why is this bad?
13     /// Methods named `iter` or `iter_mut` conventionally return an `Iterator`.
14     ///
15     /// ### Example
16     /// ```rust
17     /// // `String` does not implement `Iterator`
18     /// struct Data {}
19     /// impl Data {
20     ///     fn iter(&self) -> String {
21     ///         todo!()
22     ///     }
23     /// }
24     /// ```
25     /// Use instead:
26     /// ```rust
27     /// use std::str::Chars;
28     /// struct Data {}
29     /// impl Data {
30     ///    fn iter(&self) -> Chars<'static> {
31     ///        todo!()
32     ///    }
33     /// }
34     /// ```
35     pub ITER_NOT_RETURNING_ITERATOR,
36     pedantic,
37     "methods named `iter` or `iter_mut` that do not return an `Iterator`"
38 }
39
40 declare_lint_pass!(IterNotReturningIterator => [ITER_NOT_RETURNING_ITERATOR]);
41
42 impl LateLintPass<'_> for IterNotReturningIterator {
43     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'tcx>) {
44         let name: &str = &impl_item.ident.name.as_str();
45         if_chain! {
46             if let ImplItemKind::Fn(fn_sig, _) = &impl_item.kind;
47             let ret_ty = return_ty(cx, impl_item.hir_id());
48             if matches!(name, "iter" | "iter_mut");
49             if let [param] = cx.tcx.fn_arg_names(impl_item.def_id);
50             if param.name == kw::SelfLower;
51             if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
52             if !implements_trait(cx, ret_ty, iter_trait_id, &[]);
53
54             then {
55                 span_lint(
56                     cx,
57                     ITER_NOT_RETURNING_ITERATOR,
58                     fn_sig.span,
59                     &format!("this method is named `{}` but its return type does not implement `Iterator`", name),
60                 );
61             }
62         }
63     }
64 }