@@ -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