diff options
| author | Lzu Tao <taolzu@gmail.com> | 2020-10-08 14:21:12 +0000 |
|---|---|---|
| committer | Lzu Tao <taolzu@gmail.com> | 2020-10-08 14:26:21 +0000 |
| commit | ab226bda9a7ad56d2d417ab9451d5980c9fd35cd (patch) | |
| tree | f7ce01ee1e54780252cb7ea88d3516d92dfcf667 /compiler | |
| parent | 382848989f91fa2c25390f0d5c1e8b1ae94f47df (diff) | |
| download | rust-ab226bda9a7ad56d2d417ab9451d5980c9fd35cd.tar.gz rust-ab226bda9a7ad56d2d417ab9451d5980c9fd35cd.zip | |
Suggest removing &mut from borrow of &mut
Fix a typo: minding -> binding Add test for &mut &mut
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs | 68 |
2 files changed, 37 insertions, 33 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index da7677f802b..92a2baa30ee 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -813,7 +813,7 @@ pub struct BlockTailInfo { /// argument, or the return place. #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] 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. pub mutability: Mutability, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs index 9728662c984..e1af6fc07cf 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -1,11 +1,11 @@ use rustc_hir as hir; use rustc_hir::Node; 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::ty::{self, Ty, TyCtxt}; use rustc_span::source_map::DesugaringKind; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; 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. PlaceRef { local, projection: [] } - if { - self.body - .local_decls - .get(local) - .map(|local_decl| { - if let Some(box LocalInfo::User(ClearCrossCrate::Set( - 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) - } => + if self + .body + .local_decls + .get(local) + .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) + .unwrap_or(false) => { err.span_label(span, format!("cannot {ACT}", ACT = act)); 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>( tcx: TyCtxt<'tcx>, local_decl: &mir::LocalDecl<'tcx>, |
