diff options
| author | Quentin Santos <qsantos@qsantos.fr> | 2025-01-01 22:14:17 +0100 |
|---|---|---|
| committer | Quentin Santos <qsantos@qsantos.fr> | 2025-01-01 22:16:07 +0100 |
| commit | 7331cc0f81d97fbc4f4eb47890cb10fe7c275696 (patch) | |
| tree | 11cc0dfa872775d78cef16f1990432e46f7c6e76 | |
| parent | 27acfd8a5b9dd1eb91e044e07201b4a9044a2bbd (diff) | |
| download | rust-7331cc0f81d97fbc4f4eb47890cb10fe7c275696.tar.gz rust-7331cc0f81d97fbc4f4eb47890cb10fe7c275696.zip | |
Only complain about default Iterator::last()
| -rw-r--r-- | clippy_lints/src/methods/double_ended_iterator_last.rs | 17 | ||||
| -rw-r--r-- | tests/ui/double_ended_iterator_last.fixed | 18 | ||||
| -rw-r--r-- | tests/ui/double_ended_iterator_last.rs | 18 |
3 files changed, 52 insertions, 1 deletions
diff --git a/clippy_lints/src/methods/double_ended_iterator_last.rs b/clippy_lints/src/methods/double_ended_iterator_last.rs index dec59b1c34e..118ab7cd93b 100644 --- a/clippy_lints/src/methods/double_ended_iterator_last.rs +++ b/clippy_lints/src/methods/double_ended_iterator_last.rs @@ -4,14 +4,29 @@ use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; +use rustc_middle::ty::Instance; use rustc_span::{Span, sym}; use super::DOUBLE_ENDED_ITERATOR_LAST; pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Expr<'_>, call_span: Span) { + let typeck = cx.typeck_results(); + + // if the "last" method is that of Iterator if is_trait_method(cx, expr, sym::Iterator) + // if self implements DoubleEndedIterator && let Some(deiter_id) = cx.tcx.get_diagnostic_item(sym::DoubleEndedIterator) - && implements_trait(cx, cx.typeck_results().expr_ty(self_expr).peel_refs(), deiter_id, &[]) + && let self_type = cx.typeck_results().expr_ty(self_expr) + && implements_trait(cx, self_type.peel_refs(), deiter_id, &[]) + // resolve the method definition + && let id = typeck.type_dependent_def_id(expr.hir_id).unwrap() + && let args = typeck.node_args(expr.hir_id) + && let Ok(Some(fn_def)) = Instance::try_resolve(cx.tcx, cx.typing_env(), id, args) + // find the provided definition of Iterator::last + && let Some(item) = cx.tcx.get_diagnostic_item(sym::Iterator) + && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name == sym!(last)) + // if the resolved method is the same as the provided definition + && fn_def.def_id() == last_def.def_id { span_lint_and_sugg( cx, diff --git a/tests/ui/double_ended_iterator_last.fixed b/tests/ui/double_ended_iterator_last.fixed index cfafd104576..06c48e33753 100644 --- a/tests/ui/double_ended_iterator_last.fixed +++ b/tests/ui/double_ended_iterator_last.fixed @@ -32,4 +32,22 @@ fn main() { } } let _ = SimpleIterator.last(); + + // Should not apply to custom implementations of last() + struct CustomLast; + impl Iterator for CustomLast { + type Item = (); + fn next(&mut self) -> Option<Self::Item> { + Some(()) + } + fn last(self) -> Option<Self::Item> { + Some(()) + } + } + impl DoubleEndedIterator for CustomLast { + fn next_back(&mut self) -> Option<Self::Item> { + Some(()) + } + } + let _ = CustomLast.last(); } diff --git a/tests/ui/double_ended_iterator_last.rs b/tests/ui/double_ended_iterator_last.rs index ae80fb64838..9c13b496d11 100644 --- a/tests/ui/double_ended_iterator_last.rs +++ b/tests/ui/double_ended_iterator_last.rs @@ -32,4 +32,22 @@ fn main() { } } let _ = SimpleIterator.last(); + + // Should not apply to custom implementations of last() + struct CustomLast; + impl Iterator for CustomLast { + type Item = (); + fn next(&mut self) -> Option<Self::Item> { + Some(()) + } + fn last(self) -> Option<Self::Item> { + Some(()) + } + } + impl DoubleEndedIterator for CustomLast { + fn next_back(&mut self) -> Option<Self::Item> { + Some(()) + } + } + let _ = CustomLast.last(); } |
