Expand mutable capture check for is_iter_with_side_effects()

This commit is contained in:
yanglsh 2025-04-01 20:14:59 +08:00
parent c6d76bb69d
commit a50e043d32
13 changed files with 202 additions and 128 deletions

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::{implements_trait, is_iter_with_side_effects};
use clippy_utils::ty::{has_non_owning_mutable_access, implements_trait};
use clippy_utils::{is_mutable, is_trait_method, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Node, PatKind};
@ -28,11 +28,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp
// if the resolved method is the same as the provided definition
&& fn_def.def_id() == last_def.def_id
&& let self_ty = cx.typeck_results().expr_ty(self_expr)
&& !is_iter_with_side_effects(cx, self_ty)
&& !has_non_owning_mutable_access(cx, self_ty)
{
let mut sugg = vec![(call_span, String::from("next_back()"))];
let mut dont_apply = false;
// if `self_expr` is a reference, it is mutable because it is used for `.last()`
// TODO: Change this to lint only when the referred iterator is not used later. If it is used later,
// changing to `next_back()` may change its behavior.
if !(is_mutable(cx, self_expr) || self_type.is_ref()) {
if let Some(hir_id) = path_to_local(self_expr)
&& let Node::Pat(pat) = cx.tcx.hir_node(hir_id)

View file

@ -5,7 +5,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{
get_type_diagnostic_name, is_iter_with_side_effects, make_normalized_projection, make_projection,
get_type_diagnostic_name, has_non_owning_mutable_access, make_normalized_projection, make_projection,
};
use clippy_utils::{
CaptureKind, can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local,
@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
call_span: Span,
) {
let iter_ty = cx.typeck_results().expr_ty(iter_expr);
if is_iter_with_side_effects(cx, iter_ty) {
if has_non_owning_mutable_access(cx, iter_ty) {
return; // don't lint if the iterator has side effects
}