Do not remove identity mapping if mandatory mutability would be lost (#13905)

Removing `.map(identity)` may result in invalid code if the receiver of
`map()` is an immutable binding, and the result of `map()` is used as
the receiver of a method call expecting a mutable reference.

Fix #13904

changelog: [`map_identity`]: do not lint if this would cause mandatory
mutability to be lost
This commit is contained in:
Alex Macleod 2025-01-07 13:43:46 +00:00 committed by GitHub
commit f5ca68f9db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 56 additions and 3 deletions

View file

@ -1,8 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
use clippy_utils::{is_expr_untyped_identity_function, is_trait_method, path_to_local};
use rustc_ast::BindingMode;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{self as hir, Node, PatKind};
use rustc_lint::LateContext;
use rustc_span::{Span, sym};
@ -24,6 +25,16 @@ pub(super) fn check(
&& is_expr_untyped_identity_function(cx, map_arg)
&& let Some(sugg_span) = expr.span.trim_start(caller.span)
{
// If the result of `.map(identity)` is used as a mutable reference,
// the caller must not be an immutable binding.
if cx.typeck_results().expr_ty_adjusted(expr).is_mutable_ptr()
&& let Some(hir_id) = path_to_local(caller)
&& let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
&& !matches!(pat.kind, PatKind::Binding(BindingMode::MUT, ..))
{
return;
}
span_lint_and_sugg(
cx,
MAP_IDENTITY,