Skip to content

Commit e5931ad

Browse files
committed
fix autoborrow/mutability checks
1 parent f8dd38c commit e5931ad

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

clippy_lints/src/unnecessary_indexing.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ use clippy_utils::source::snippet;
55
use clippy_utils::ty::is_type_diagnostic_item;
66
use clippy_utils::visitors::for_each_expr;
77
use clippy_utils::{eq_expr_value, path_to_local, path_to_local_id};
8-
use rustc_ast::{BorrowKind, LitKind, Mutability};
8+
use rustc_ast::{LitKind, Mutability};
99
use rustc_errors::Applicability;
1010
use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, UnOp};
1111
use rustc_lint::{LateContext, LateLintPass};
1212
use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability};
13+
use rustc_middle::ty::{self};
1314
use rustc_session::declare_lint_pass;
1415
use rustc_span::sym;
1516

@@ -53,19 +54,16 @@ impl LateLintPass<'_> for UnnecessaryIndexing {
5354
&& let ExprKind::MethodCall(method, conditional_receiver, _, _) = unary_inner.kind
5455
&& method.ident.as_str() == "is_empty"
5556
&& let typeck_results = cx.typeck_results()
56-
// do not lint on mutable auto borrows (https://github.com/rust-lang/rust-clippy/pull/12464#discussion_r1600352696)
57-
&& let adjustments = typeck_results.expr_adjustments(conditional_receiver)
58-
&& !adjustments.iter().any(|adjustment| {
59-
matches!(adjustment.kind, Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut {
60-
allow_two_phase_borrow: _
61-
})))
62-
})
63-
// do not lint if receiver is a mutable reference
64-
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = conditional_receiver.kind
65-
&& let expr_ty = typeck_results.expr_ty(conditional_receiver).peel_refs()
66-
&& (expr_ty.is_slice() || expr_ty.is_array() || is_type_diagnostic_item(cx, expr_ty, sym::Vec))
57+
&& let expr_ty = typeck_results.expr_ty(conditional_receiver)
58+
&& let peeled = expr_ty.peel_refs()
59+
&& (peeled.is_slice() || peeled.is_array() || is_type_diagnostic_item(cx, peeled, sym::Vec))
6760
&& let ExprKind::Block(block, _) = if_expr.then.kind
6861
{
62+
// do not lint if conditional receiver is mutable reference
63+
if let ty::Ref(_, _, Mutability::Mut) = expr_ty.kind() {
64+
return;
65+
}
66+
6967
let result = process_indexing(cx, block, conditional_receiver);
7068

7169
if let Some(r) = result
@@ -178,6 +176,8 @@ fn process_indexing<'a>(
178176
// if res == Some(()), then mutation occurred
179177
// & therefore we should not lint on this
180178
let res = for_each_expr(block.stmts, |x| {
179+
let adjustments = cx.typeck_results().expr_adjustments(x);
180+
181181
if let ExprKind::Index(receiver, index, _) = x.kind
182182
&& let ExprKind::Lit(lit) = index.kind
183183
&& let LitKind::Int(val, _) = lit.node
@@ -195,6 +195,14 @@ fn process_indexing<'a>(
195195
} else {
196196
extra_exprs.push(x);
197197
};
198+
} else if adjustments.iter().any(|adjustment| {
199+
matches!(
200+
adjustment.kind,
201+
Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. }))
202+
)
203+
}) {
204+
// do not lint on mutable auto borrows (https://github.com/rust-lang/rust-clippy/pull/12464#discussion_r1600352696)
205+
return ControlFlow::Break(());
198206
} else if let ExprKind::AddrOf(_, Mutability::Mut, val) = x.kind
199207
&& eq_expr_value(cx, conditional_receiver, val)
200208
{

tests/ui/unnecessary_indexing.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,20 @@ fn main() {
112112
let b = a[0];
113113
drop(&mut a);
114114
}
115+
116+
// dont lint on mutable auto borrow
117+
let mut a = vec![1, 2, 3];
118+
if !a.is_empty() {
119+
a.push(1);
120+
let b = a[0];
121+
b;
122+
}
123+
124+
// do not lint if conditional receiver is mutable reference
125+
let a = &mut vec![1, 2, 3];
126+
if !a.is_empty() {
127+
let b = a[0];
128+
a;
129+
b;
130+
}
115131
}

0 commit comments

Comments
 (0)