]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use crate::utils::{is_copy, match_path, paths, span_lint_and_note}; |
2 | use rustc_hir::{Impl, Item, ItemKind}; | |
3 | use rustc_lint::{LateContext, LateLintPass}; | |
4 | use rustc_session::{declare_lint_pass, declare_tool_lint}; | |
5 | ||
6 | declare_clippy_lint! { | |
7 | /// **What it does:** Checks for types that implement `Copy` as well as | |
8 | /// `Iterator`. | |
9 | /// | |
10 | /// **Why is this bad?** Implicit copies can be confusing when working with | |
11 | /// iterator combinators. | |
12 | /// | |
13 | /// **Known problems:** None. | |
14 | /// | |
15 | /// **Example:** | |
16 | /// ```rust,ignore | |
17 | /// #[derive(Copy, Clone)] | |
18 | /// struct Countdown(u8); | |
19 | /// | |
20 | /// impl Iterator for Countdown { | |
21 | /// // ... | |
22 | /// } | |
23 | /// | |
24 | /// let a: Vec<_> = my_iterator.take(1).collect(); | |
25 | /// let b: Vec<_> = my_iterator.collect(); | |
26 | /// ``` | |
27 | pub COPY_ITERATOR, | |
28 | pedantic, | |
29 | "implementing `Iterator` on a `Copy` type" | |
30 | } | |
31 | ||
32 | declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); | |
33 | ||
34 | impl<'tcx> LateLintPass<'tcx> for CopyIterator { | |
35 | fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { | |
36 | if let ItemKind::Impl(Impl { | |
37 | of_trait: Some(ref trait_ref), | |
38 | .. | |
39 | }) = item.kind | |
40 | { | |
41 | let ty = cx.tcx.type_of(item.def_id); | |
42 | ||
43 | if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) { | |
44 | span_lint_and_note( | |
45 | cx, | |
46 | COPY_ITERATOR, | |
47 | item.span, | |
48 | "you are implementing `Iterator` on a `Copy` type", | |
49 | None, | |
50 | "consider implementing `IntoIterator` instead", | |
51 | ); | |
52 | } | |
53 | } | |
54 | } | |
55 | } |