@@ -4,14 +4,29 @@ use clippy_utils::ty::implements_trait;
44use rustc_errors::Applicability;
55use rustc_hir::Expr;
66use rustc_lint::LateContext;
7+ use rustc_middle::ty::Instance;
78use rustc_span::{Span, sym};
89
910use super::DOUBLE_ENDED_ITERATOR_LAST;
1011
1112pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Expr<'_>, call_span: Span) {
13+ let typeck = cx.typeck_results();
14+
15+ // if the "last" method is that of Iterator
1216 if is_trait_method(cx, expr, sym::Iterator)
17+ // if self implements DoubleEndedIterator
1318 && let Some(deiter_id) = cx.tcx.get_diagnostic_item(sym::DoubleEndedIterator)
14- && implements_trait(cx, cx.typeck_results().expr_ty(self_expr).peel_refs(), deiter_id, &[])
19+ && let self_type = cx.typeck_results().expr_ty(self_expr)
20+ && implements_trait(cx, self_type.peel_refs(), deiter_id, &[])
21+ // resolve the method definition
22+ && let id = typeck.type_dependent_def_id(expr.hir_id).unwrap()
23+ && let args = typeck.node_args(expr.hir_id)
24+ && let Ok(Some(fn_def)) = Instance::try_resolve(cx.tcx, cx.typing_env(), id, args)
25+ // find the provided definition of Iterator::last
26+ && let Some(item) = cx.tcx.get_diagnostic_item(sym::Iterator)
27+ && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name == sym!(last))
28+ // if the resolved method is the same as the provided definition
29+ && fn_def.def_id() == last_def.def_id
1530 {
1631 span_lint_and_sugg(
1732 cx,
0 commit comments