Skip to content

Commit 3525087

Browse files
committed
Auto merge of #77110 - lzutao:e0596-amp_mut, r=davidtwco
Suggest removing `&mut` from a `&mut borrow` Modify the code added in #54720. Closes #75871
2 parents 6b8d791 + ab226bd commit 3525087

File tree

4 files changed

+60
-46
lines changed

4 files changed

+60
-46
lines changed

compiler/rustc_middle/src/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ pub struct BlockTailInfo {
813813
/// argument, or the return place.
814814
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
815815
pub struct LocalDecl<'tcx> {
816-
/// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
816+
/// Whether this is a mutable binding (i.e., `let x` or `let mut x`).
817817
///
818818
/// Temporaries and the return place are always mutable.
819819
pub mutability: Mutability,

compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use rustc_hir as hir;
22
use rustc_hir::Node;
33
use rustc_index::vec::Idx;
4-
use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalInfo, Location};
4+
use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location};
55
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
66
use rustc_middle::ty::{self, Ty, TyCtxt};
77
use rustc_span::source_map::DesugaringKind;
8-
use rustc_span::symbol::kw;
8+
use rustc_span::symbol::{kw, Symbol};
99
use rustc_span::Span;
1010

1111
use crate::borrow_check::diagnostics::BorrowedContentSource;
@@ -211,36 +211,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
211211

212212
// Suggest removing a `&mut` from the use of a mutable reference.
213213
PlaceRef { local, projection: [] }
214-
if {
215-
self.body
216-
.local_decls
217-
.get(local)
218-
.map(|local_decl| {
219-
if let Some(box LocalInfo::User(ClearCrossCrate::Set(
220-
mir::BindingForm::ImplicitSelf(kind),
221-
))) = local_decl.local_info
222-
{
223-
// Check if the user variable is a `&mut self` and we can therefore
224-
// suggest removing the `&mut`.
225-
//
226-
// Deliberately fall into this case for all implicit self types,
227-
// so that we don't fall in to the next case with them.
228-
kind == mir::ImplicitSelfKind::MutRef
229-
} else if Some(kw::SelfLower) == self.local_names[local] {
230-
// Otherwise, check if the name is the self kewyord - in which case
231-
// we have an explicit self. Do the same thing in this case and check
232-
// for a `self: &mut Self` to suggest removing the `&mut`.
233-
if let ty::Ref(_, _, hir::Mutability::Mut) = local_decl.ty.kind() {
234-
true
235-
} else {
236-
false
237-
}
238-
} else {
239-
false
240-
}
241-
})
242-
.unwrap_or(false)
243-
} =>
214+
if self
215+
.body
216+
.local_decls
217+
.get(local)
218+
.map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local]))
219+
.unwrap_or(false) =>
244220
{
245221
err.span_label(span, format!("cannot {ACT}", ACT = act));
246222
err.span_label(span, "try removing `&mut` here");
@@ -581,6 +557,34 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
581557
}
582558
}
583559

560+
fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
561+
debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
562+
563+
match local_decl.local_info.as_deref() {
564+
// Check if mutably borrowing a mutable reference.
565+
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
566+
mir::VarBindingForm {
567+
binding_mode: ty::BindingMode::BindByValue(Mutability::Not), ..
568+
},
569+
)))) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
570+
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(kind)))) => {
571+
// Check if the user variable is a `&mut self` and we can therefore
572+
// suggest removing the `&mut`.
573+
//
574+
// Deliberately fall into this case for all implicit self types,
575+
// so that we don't fall in to the next case with them.
576+
*kind == mir::ImplicitSelfKind::MutRef
577+
}
578+
_ if Some(kw::SelfLower) == local_name => {
579+
// Otherwise, check if the name is the `self` keyword - in which case
580+
// we have an explicit self. Do the same thing in this case and check
581+
// for a `self: &mut Self` to suggest removing the `&mut`.
582+
matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut))
583+
}
584+
_ => false,
585+
}
586+
}
587+
584588
fn suggest_ampmut_self<'tcx>(
585589
tcx: TyCtxt<'tcx>,
586590
local_decl: &mir::LocalDecl<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Suggest not mutably borrowing a mutable reference
2+
#![crate_type = "rlib"]
23

3-
fn main() {
4-
f(&mut 0)
4+
pub fn f(b: &mut i32) {
5+
g(&mut b);
6+
//~^ ERROR cannot borrow
7+
g(&mut &mut b);
8+
//~^ ERROR cannot borrow
59
}
610

7-
fn f(b: &mut i32) {
8-
g(&mut b) //~ ERROR cannot borrow
9-
}
10-
11-
fn g(_: &mut i32) {}
11+
pub fn g(_: &mut i32) {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
2-
--> $DIR/mut-borrow-of-mut-ref.rs:8:7
2+
--> $DIR/mut-borrow-of-mut-ref.rs:5:7
33
|
4-
LL | fn f(b: &mut i32) {
5-
| - help: consider changing this to be mutable: `mut b`
6-
LL | g(&mut b)
7-
| ^^^^^^ cannot borrow as mutable
4+
LL | g(&mut b);
5+
| ^^^^^^
6+
| |
7+
| cannot borrow as mutable
8+
| try removing `&mut` here
89

9-
error: aborting due to previous error
10+
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
11+
--> $DIR/mut-borrow-of-mut-ref.rs:7:12
12+
|
13+
LL | g(&mut &mut b);
14+
| ^^^^^^
15+
| |
16+
| cannot borrow as mutable
17+
| try removing `&mut` here
18+
19+
error: aborting due to 2 previous errors
1020

1121
For more information about this error, try `rustc --explain E0596`.

0 commit comments

Comments
 (0)