diff options
| author | bors <bors@rust-lang.org> | 2022-01-10 12:34:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-01-10 12:34:15 +0000 |
| commit | b66dbe87f10c56f86270ce6eb0efd88e6e7fc1c9 (patch) | |
| tree | 63a1fdedbd738104edf6cc2ef92e50d598606840 | |
| parent | 18163617388c32edce09ff3d31adc86e0141cc7d (diff) | |
| parent | d98339d3e002b8b1bddf225e98c3140d7f1cecc7 (diff) | |
| download | rust-b66dbe87f10c56f86270ce6eb0efd88e6e7fc1c9.tar.gz rust-b66dbe87f10c56f86270ce6eb0efd88e6e7fc1c9.zip | |
Auto merge of #8228 - Jarcho:iter_not_returning_iterator_8225, r=giraffate
fix `iter_not_returning_iterator` fixes #8225 changelog: Handle type projections in `iter_not_returning_iterator` changelog: Don't lint `iter_not_returning_iterator` in trait implementations changelog: Lint `iter_not_returning_iterator` in trait definitions
| -rw-r--r-- | clippy_lints/src/iter_not_returning_iterator.rs | 65 | ||||
| -rw-r--r-- | tests/ui/iter_not_returning_iterator.rs | 20 | ||||
| -rw-r--r-- | tests/ui/iter_not_returning_iterator.stderr | 8 |
3 files changed, 72 insertions, 21 deletions
diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index 0af6b3b7d46..017a8a779d9 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -1,8 +1,7 @@ -use clippy_utils::{diagnostics::span_lint, return_ty, ty::implements_trait}; -use rustc_hir::{ImplItem, ImplItemKind}; +use clippy_utils::{diagnostics::span_lint, get_parent_node, ty::implements_trait}; +use rustc_hir::{def_id::LocalDefId, FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::kw; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -41,25 +40,51 @@ declare_clippy_lint! { declare_lint_pass!(IterNotReturningIterator => [ITER_NOT_RETURNING_ITERATOR]); impl LateLintPass<'_> for IterNotReturningIterator { - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'tcx>) { - let name = impl_item.ident.name.as_str(); - if_chain! { - if let ImplItemKind::Fn(fn_sig, _) = &impl_item.kind; - let ret_ty = return_ty(cx, impl_item.hir_id()); - if matches!(name, "iter" | "iter_mut"); - if let [param] = cx.tcx.fn_arg_names(impl_item.def_id); - if param.name == kw::SelfLower; - if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - if !implements_trait(cx, ret_ty, iter_trait_id, &[]); + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { + let name = item.ident.name.as_str(); + if matches!(name, "iter" | "iter_mut") { + if let TraitItemKind::Fn(fn_sig, _) = &item.kind { + check_sig(cx, name, fn_sig, item.def_id); + } + } + } - then { - span_lint( - cx, - ITER_NOT_RETURNING_ITERATOR, - fn_sig.span, - &format!("this method is named `{}` but its return type does not implement `Iterator`", name), - ); + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) { + let name = item.ident.name.as_str(); + if matches!(name, "iter" | "iter_mut") + && !matches!( + get_parent_node(cx.tcx, item.hir_id()), + Some(Node::Item(Item { kind: ItemKind::Impl(i), .. })) if i.of_trait.is_some() + ) + { + if let ImplItemKind::Fn(fn_sig, _) = &item.kind { + check_sig(cx, name, fn_sig, item.def_id); } } } } + +fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefId) { + if sig.decl.implicit_self.has_implicit_self() { + let ret_ty = cx.tcx.fn_sig(fn_id).skip_binder().output(); + let ret_ty = cx + .tcx + .try_normalize_erasing_regions(cx.param_env, ret_ty) + .unwrap_or(ret_ty); + if cx + .tcx + .get_diagnostic_item(sym::Iterator) + .map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[])) + { + span_lint( + cx, + ITER_NOT_RETURNING_ITERATOR, + sig.span, + &format!( + "this method is named `{}` but its return type does not implement `Iterator`", + name + ), + ); + } + } +} diff --git a/tests/ui/iter_not_returning_iterator.rs b/tests/ui/iter_not_returning_iterator.rs index 377f760b3c4..2c91e02e842 100644 --- a/tests/ui/iter_not_returning_iterator.rs +++ b/tests/ui/iter_not_returning_iterator.rs @@ -44,4 +44,24 @@ impl Iterator for Counter { } } +// Issue #8225 +trait Iter { + type I; + fn iter(&self) -> Self::I; +} + +impl Iter for () { + type I = core::slice::Iter<'static, ()>; + fn iter(&self) -> Self::I { + [].iter() + } +} + +struct S; +impl S { + fn iter(&self) -> <() as Iter>::I { + ().iter() + } +} + fn main() {} diff --git a/tests/ui/iter_not_returning_iterator.stderr b/tests/ui/iter_not_returning_iterator.stderr index 2273cd0be66..44f02955836 100644 --- a/tests/ui/iter_not_returning_iterator.stderr +++ b/tests/ui/iter_not_returning_iterator.stderr @@ -12,5 +12,11 @@ error: this method is named `iter_mut` but its return type does not implement `I LL | fn iter_mut(&self) -> Counter2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: this method is named `iter` but its return type does not implement `Iterator` + --> $DIR/iter_not_returning_iterator.rs:50:5 + | +LL | fn iter(&self) -> Self::I; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors |
