mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Suggest removing &mut from borrow of &mut
Fix a typo: minding -> binding Add test for &mut &mut
This commit is contained in:
parent
382848989f
commit
ab226bda9a
@ -813,7 +813,7 @@ pub struct BlockTailInfo {
|
|||||||
/// argument, or the return place.
|
/// argument, or the return place.
|
||||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
|
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
|
||||||
pub struct LocalDecl<'tcx> {
|
pub struct LocalDecl<'tcx> {
|
||||||
/// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
|
/// Whether this is a mutable binding (i.e., `let x` or `let mut x`).
|
||||||
///
|
///
|
||||||
/// Temporaries and the return place are always mutable.
|
/// Temporaries and the return place are always mutable.
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalInfo, Location};
|
use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location};
|
||||||
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::source_map::DesugaringKind;
|
use rustc_span::source_map::DesugaringKind;
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::{kw, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::borrow_check::diagnostics::BorrowedContentSource;
|
use crate::borrow_check::diagnostics::BorrowedContentSource;
|
||||||
@ -211,36 +211,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
// Suggest removing a `&mut` from the use of a mutable reference.
|
// Suggest removing a `&mut` from the use of a mutable reference.
|
||||||
PlaceRef { local, projection: [] }
|
PlaceRef { local, projection: [] }
|
||||||
if {
|
if self
|
||||||
self.body
|
.body
|
||||||
.local_decls
|
.local_decls
|
||||||
.get(local)
|
.get(local)
|
||||||
.map(|local_decl| {
|
.map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local]))
|
||||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(
|
.unwrap_or(false) =>
|
||||||
mir::BindingForm::ImplicitSelf(kind),
|
|
||||||
))) = local_decl.local_info
|
|
||||||
{
|
|
||||||
// Check if the user variable is a `&mut self` and we can therefore
|
|
||||||
// suggest removing the `&mut`.
|
|
||||||
//
|
|
||||||
// Deliberately fall into this case for all implicit self types,
|
|
||||||
// so that we don't fall in to the next case with them.
|
|
||||||
kind == mir::ImplicitSelfKind::MutRef
|
|
||||||
} else if Some(kw::SelfLower) == self.local_names[local] {
|
|
||||||
// Otherwise, check if the name is the self kewyord - in which case
|
|
||||||
// we have an explicit self. Do the same thing in this case and check
|
|
||||||
// for a `self: &mut Self` to suggest removing the `&mut`.
|
|
||||||
if let ty::Ref(_, _, hir::Mutability::Mut) = local_decl.ty.kind() {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
} =>
|
|
||||||
{
|
{
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
err.span_label(span, "try removing `&mut` here");
|
err.span_label(span, "try removing `&mut` here");
|
||||||
@ -581,6 +557,34 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
|
||||||
|
debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
|
||||||
|
|
||||||
|
match local_decl.local_info.as_deref() {
|
||||||
|
// Check if mutably borrowing a mutable reference.
|
||||||
|
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||||
|
mir::VarBindingForm {
|
||||||
|
binding_mode: ty::BindingMode::BindByValue(Mutability::Not), ..
|
||||||
|
},
|
||||||
|
)))) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
||||||
|
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(kind)))) => {
|
||||||
|
// Check if the user variable is a `&mut self` and we can therefore
|
||||||
|
// suggest removing the `&mut`.
|
||||||
|
//
|
||||||
|
// Deliberately fall into this case for all implicit self types,
|
||||||
|
// so that we don't fall in to the next case with them.
|
||||||
|
*kind == mir::ImplicitSelfKind::MutRef
|
||||||
|
}
|
||||||
|
_ if Some(kw::SelfLower) == local_name => {
|
||||||
|
// Otherwise, check if the name is the `self` keyword - in which case
|
||||||
|
// we have an explicit self. Do the same thing in this case and check
|
||||||
|
// for a `self: &mut Self` to suggest removing the `&mut`.
|
||||||
|
matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut))
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn suggest_ampmut_self<'tcx>(
|
fn suggest_ampmut_self<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
local_decl: &mir::LocalDecl<'tcx>,
|
local_decl: &mir::LocalDecl<'tcx>,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// Suggest not mutably borrowing a mutable reference
|
// Suggest not mutably borrowing a mutable reference
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
fn main() {
|
pub fn f(b: &mut i32) {
|
||||||
f(&mut 0)
|
g(&mut b);
|
||||||
|
//~^ ERROR cannot borrow
|
||||||
|
g(&mut &mut b);
|
||||||
|
//~^ ERROR cannot borrow
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f(b: &mut i32) {
|
pub fn g(_: &mut i32) {}
|
||||||
g(&mut b) //~ ERROR cannot borrow
|
|
||||||
}
|
|
||||||
|
|
||||||
fn g(_: &mut i32) {}
|
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
|
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
|
||||||
--> $DIR/mut-borrow-of-mut-ref.rs:8:7
|
--> $DIR/mut-borrow-of-mut-ref.rs:5:7
|
||||||
|
|
|
|
||||||
LL | fn f(b: &mut i32) {
|
LL | g(&mut b);
|
||||||
| - help: consider changing this to be mutable: `mut b`
|
| ^^^^^^
|
||||||
LL | g(&mut b)
|
| |
|
||||||
| ^^^^^^ cannot borrow as mutable
|
| cannot borrow as mutable
|
||||||
|
| try removing `&mut` here
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
|
||||||
|
--> $DIR/mut-borrow-of-mut-ref.rs:7:12
|
||||||
|
|
|
||||||
|
LL | g(&mut &mut b);
|
||||||
|
| ^^^^^^
|
||||||
|
| |
|
||||||
|
| cannot borrow as mutable
|
||||||
|
| try removing `&mut` here
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0596`.
|
For more information about this error, try `rustc --explain E0596`.
|
||||||
|
Loading…
Reference in New Issue
Block a user