Only complain about default Iterator::last()
This commit is contained in:
parent
27acfd8a5b
commit
7331cc0f81
3 changed files with 52 additions and 1 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue