Don't lint with `map_clone` if current type is `Option` or `Result` and method call is `as_ref`.

This commit is contained in:
Guillaume Gomez 2024-01-09 17:31:59 +01:00
parent e90eea7894
commit 83ae5edd50
1 changed files with 11 additions and 4 deletions

View File

@ -15,22 +15,29 @@ use rustc_span::{sym, Span};
use super::MAP_CLONE;
fn should_run_lint(cx: &LateContext<'_>, method_id: DefId) -> bool {
fn should_run_lint(cx: &LateContext<'_>, e: &hir::Expr<'_>, method_id: DefId) -> bool {
if is_diag_trait_item(cx, method_id, sym::Iterator) {
return true;
}
if !cx.tcx.impl_of_method(method_id).map_or(false, |id| {
is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Option)
|| is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Result)
let identity = cx.tcx.type_of(id).instantiate_identity();
is_type_diagnostic_item(cx, identity, sym::Option) || is_type_diagnostic_item(cx, identity, sym::Result)
}) {
return false;
}
// We check if the previous method call is `as_ref`.
if let hir::ExprKind::MethodCall(path1, receiver, _, _) = &e.kind
&& let hir::ExprKind::MethodCall(path2, _, _, _) = &receiver.kind
{
return path2.ident.name != sym::as_ref || path1.ident.name != sym::map;
}
return true;
}
pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& should_run_lint(cx, method_id)
&& should_run_lint(cx, e, method_id)
{
match arg.kind {
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {