Skip to content

Commit 11b28d4

Browse files
Implement mut ref/mut ref mut
1 parent 4b10cb2 commit 11b28d4

14 files changed

+34
-29
lines changed

clippy_lints/src/functions/misnamed_getters.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
2424
let name = ident.name.as_str();
2525

2626
let name = match decl.implicit_self {
27-
ImplicitSelfKind::MutRef => {
27+
ImplicitSelfKind::RefMut => {
2828
let Some(name) = name.strip_suffix("_mut") else {
2929
return;
3030
};
3131
name
3232
},
33-
ImplicitSelfKind::Imm | ImplicitSelfKind::Mut | ImplicitSelfKind::ImmRef => name,
33+
ImplicitSelfKind::Imm | ImplicitSelfKind::Mut | ImplicitSelfKind::RefImm => name,
3434
ImplicitSelfKind::None => return,
3535
};
3636

clippy_lints/src/index_refutable_slice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
9797
value_hir_id,
9898
ident,
9999
sub_pat,
100-
) = pat.kind
100+
) = pat.kind && by_ref != hir::ByRef::Yes(hir::Mutability::Mut)
101101
{
102102
// This block catches bindings with sub patterns. It would be hard to build a correct suggestion
103103
// for them and it's likely that the user knows what they are doing in such a case.
@@ -115,7 +115,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
115115
if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
116116
// The values need to use the `ref` keyword if they can't be copied.
117117
// This will need to be adjusted if the lint want to support mutable access in the future
118-
let src_is_ref = bound_ty.is_ref() && by_ref != hir::ByRef::Yes;
118+
let src_is_ref = bound_ty.is_ref() && by_ref == hir::ByRef::No;
119119
let needs_ref = !(src_is_ref || is_copy(cx, *inner_ty));
120120

121121
let slice_info = slices

clippy_lints/src/iter_without_into_iter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ impl {self_ty_without_ref} {{
216216
fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) {
217217
let item_did = item.owner_id.to_def_id();
218218
let (borrow_prefix, expected_implicit_self) = match item.ident.name {
219-
sym::iter => ("&", ImplicitSelfKind::ImmRef),
220-
sym::iter_mut => ("&mut ", ImplicitSelfKind::MutRef),
219+
sym::iter => ("&", ImplicitSelfKind::RefImm),
220+
sym::iter_mut => ("&mut ", ImplicitSelfKind::RefMut),
221221
_ => return,
222222
};
223223

clippy_lints/src/len_zero.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ impl LenOutput {
384384

385385
fn expected_sig(self, self_kind: ImplicitSelfKind) -> String {
386386
let self_ref = match self_kind {
387-
ImplicitSelfKind::ImmRef => "&",
388-
ImplicitSelfKind::MutRef => "&mut ",
387+
ImplicitSelfKind::RefImm => "&",
388+
ImplicitSelfKind::RefMut => "&mut ",
389389
_ => "",
390390
};
391391
match self {
@@ -411,8 +411,8 @@ fn check_is_empty_sig<'tcx>(
411411
[arg, res] if len_output.matches_is_empty_output(cx, *res) => {
412412
matches!(
413413
(arg.kind(), self_kind),
414-
(ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::ImmRef)
415-
| (ty::Ref(_, _, Mutability::Mut), ImplicitSelfKind::MutRef)
414+
(ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::RefImm)
415+
| (ty::Ref(_, _, Mutability::Mut), ImplicitSelfKind::RefMut)
416416
) || (!arg.is_ref() && matches!(self_kind, ImplicitSelfKind::Imm | ImplicitSelfKind::Mut))
417417
},
418418
_ => false,

clippy_lints/src/matches/infallible_destructuring_match.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet_with_applicability;
33
use clippy_utils::{path_to_local_id, peel_blocks, strip_pat_refs};
44
use rustc_errors::Applicability;
5-
use rustc_hir::{ByRef, ExprKind, LetStmt, MatchSource, PatKind, QPath};
5+
use rustc_hir::{ExprKind, LetStmt, MatchSource, PatKind, QPath};
66
use rustc_lint::LateContext;
77

88
use super::INFALLIBLE_DESTRUCTURING_MATCH;
@@ -30,7 +30,7 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool {
3030
format!(
3131
"let {}({}{}) = {};",
3232
snippet_with_applicability(cx, variant_name.span, "..", &mut applicability),
33-
if binding.0 == ByRef::Yes { "ref " } else { "" },
33+
binding.prefix_str(),
3434
snippet_with_applicability(cx, local.pat.span, "..", &mut applicability),
3535
snippet_with_applicability(cx, target.span, "..", &mut applicability),
3636
),

clippy_lints/src/matches/match_as_ref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
6767
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
6868
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind
6969
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome)
70-
&& let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind
70+
&& let PatKind::Binding(BindingAnnotation(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind
7171
&& let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
7272
&& is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome)
7373
&& let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind

clippy_lints/src/matches/needless_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
178178
},
179179
)),
180180
) => {
181-
return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name;
181+
return !matches!(annot, BindingAnnotation(ByRef::Yes(_), _)) && pat_ident.name == first_seg.ident.name;
182182
},
183183
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
184184
(PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {

clippy_lints/src/matches/redundant_guards.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ fn get_pat_binding<'tcx>(
182182
if let PatKind::Binding(bind_annot, hir_id, ident, _) = pat.kind
183183
&& hir_id == local
184184
{
185-
if matches!(bind_annot.0, rustc_ast::ByRef::Yes) {
185+
if matches!(bind_annot.0, rustc_ast::ByRef::Yes(_)) {
186186
let _ = byref_ident.insert(ident);
187187
}
188188
// the second call of `replace()` returns a `Some(span)`, meaning a multi-binding pattern

clippy_lints/src/methods/clone_on_copy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub(super) fn check(
6969
_ => false,
7070
},
7171
// local binding capturing a reference
72-
Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
72+
Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes(_), _), ..)) => {
7373
return;
7474
},
7575
_ => false,

clippy_lints/src/methods/iter_kv_map.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,15 @@ pub(super) fn check<'tcx>(
6060
applicability,
6161
);
6262
} else {
63-
let ref_annotation = if annotation.0 == ByRef::Yes { "ref " } else { "" };
64-
let mut_annotation = if annotation.1 == Mutability::Mut { "mut " } else { "" };
6563
span_lint_and_sugg(
6664
cx,
6765
ITER_KV_MAP,
6866
expr.span,
6967
&format!("iterating on a map's {replacement_kind}s"),
7068
"try",
7169
format!(
72-
"{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
70+
"{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{}{bound_ident}| {})",
71+
annotation.prefix_str(),
7372
snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)
7473
),
7574
applicability,

clippy_lints/src/misc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
129129
if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
130130
return;
131131
}
132-
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
132+
if let PatKind::Binding(BindingAnnotation(ByRef::Yes(_), _), ..) = arg.pat.kind {
133133
span_lint(
134134
cx,
135135
TOPLEVEL_REF_ARG,
@@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
144144
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
145145
if !in_external_macro(cx.tcx.sess, stmt.span)
146146
&& let StmtKind::Let(local) = stmt.kind
147-
&& let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind
147+
&& let PatKind::Binding(BindingAnnotation(ByRef::Yes(mutabl), _), .., name, None) = local.pat.kind
148148
&& let Some(init) = local.init
149149
// Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
150150
&& is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id)

clippy_lints/src/question_mark.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_errors::Applicability;
1414
use rustc_hir::def::Res;
1515
use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
1616
use rustc_hir::{
17-
BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Node, PatKind, PathSegment, QPath, Stmt, StmtKind,
17+
BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt, StmtKind,
1818
};
1919
use rustc_lint::{LateContext, LateLintPass};
2020
use rustc_middle::ty::Ty;
@@ -283,9 +283,13 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
283283
let mut applicability = Applicability::MachineApplicable;
284284
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
285285
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
286+
let method_call_str = match by_ref {
287+
ByRef::Yes(Mutability::Mut) => ".as_mut()",
288+
ByRef::Yes(Mutability::Not) => ".as_ref()",
289+
ByRef::No => "",
290+
};
286291
let sugg = format!(
287-
"{receiver_str}{}?{}",
288-
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
292+
"{receiver_str}{method_call_str}?{}",
289293
if requires_semi { ";" } else { "" }
290294
);
291295
span_lint_and_sugg(

clippy_lints/src/utils/author.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
649649
BindingAnnotation::REF => "REF",
650650
BindingAnnotation::MUT => "MUT",
651651
BindingAnnotation::REF_MUT => "REF_MUT",
652+
BindingAnnotation::MUT_REF => "MUT_REF",
653+
BindingAnnotation::MUT_REF_MUT => "MUT_REF_MUT",
652654
};
653655
kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})");
654656
self.ident(name);

clippy_utils/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
9797
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
9898
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
9999
use rustc_hir::{
100-
self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr,
100+
self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, ByRef, Closure, Destination, Expr,
101101
ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item,
102102
ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy,
103103
QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
@@ -107,7 +107,6 @@ use rustc_lint::{LateContext, Level, Lint, LintContext};
107107
use rustc_middle::hir::place::PlaceBase;
108108
use rustc_middle::mir::Const;
109109
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
110-
use rustc_middle::ty::binding::BindingMode;
111110
use rustc_middle::ty::fast_reject::SimplifiedType;
112111
use rustc_middle::ty::layout::IntegerExt;
113112
use rustc_middle::ty::{
@@ -1006,11 +1005,12 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
10061005
.typeck_results()
10071006
.extract_binding_mode(cx.sess(), id, span)
10081007
.unwrap()
1008+
.0
10091009
{
1010-
BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => {
1010+
ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => {
10111011
capture = CaptureKind::Value;
10121012
},
1013-
BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => {
1013+
ByRef::Yes(Mutability::Mut) if capture != CaptureKind::Value => {
10141014
capture = CaptureKind::Ref(Mutability::Mut);
10151015
},
10161016
_ => (),
@@ -2035,7 +2035,7 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
20352035
.typeck_results()
20362036
.pat_binding_modes()
20372037
.get(pat.hir_id)
2038-
.is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_)))
2038+
.is_some_and(|mode| matches!(mode.0, ByRef::Yes(_)))
20392039
{
20402040
// If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics,
20412041
// the inner patterns become references. Don't consider this the identity function

0 commit comments

Comments
 (0)