]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/copy_iterator.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / copy_iterator.rs
1 use clippy_utils::diagnostics::span_lint_and_note;
2 use clippy_utils::ty::is_copy;
3 use rustc_hir::{Impl, Item, ItemKind};
4 use rustc_lint::{LateContext, LateLintPass};
5 use rustc_session::{declare_lint_pass, declare_tool_lint};
6 use rustc_span::sym;
7
8 use if_chain::if_chain;
9
10 declare_clippy_lint! {
11 /// ### What it does
12 /// Checks for types that implement `Copy` as well as
13 /// `Iterator`.
14 ///
15 /// ### Why is this bad?
16 /// Implicit copies can be confusing when working with
17 /// iterator combinators.
18 ///
19 /// ### Example
20 /// ```rust,ignore
21 /// #[derive(Copy, Clone)]
22 /// struct Countdown(u8);
23 ///
24 /// impl Iterator for Countdown {
25 /// // ...
26 /// }
27 ///
28 /// let a: Vec<_> = my_iterator.take(1).collect();
29 /// let b: Vec<_> = my_iterator.collect();
30 /// ```
31 #[clippy::version = "1.30.0"]
32 pub COPY_ITERATOR,
33 pedantic,
34 "implementing `Iterator` on a `Copy` type"
35 }
36
37 declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
38
39 impl<'tcx> LateLintPass<'tcx> for CopyIterator {
40 fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
41 if_chain! {
42 if let ItemKind::Impl(Impl {
43 of_trait: Some(ref trait_ref),
44 ..
45 }) = item.kind;
46 let ty = cx.tcx.type_of(item.owner_id);
47 if is_copy(cx, ty);
48 if let Some(trait_id) = trait_ref.trait_def_id();
49 if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
50 then {
51 span_lint_and_note(
52 cx,
53 COPY_ITERATOR,
54 item.span,
55 "you are implementing `Iterator` on a `Copy` type",
56 None,
57 "consider implementing `IntoIterator` instead",
58 );
59 }
60 }
61 }
62 }