|
1 | 1 | use rustc_hir as hir; |
2 | 2 | use rustc_hir::Node; |
3 | 3 | 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}; |
5 | 5 | use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; |
6 | 6 | use rustc_middle::ty::{self, Ty, TyCtxt}; |
7 | 7 | use rustc_span::source_map::DesugaringKind; |
8 | | -use rustc_span::symbol::kw; |
| 8 | +use rustc_span::symbol::{kw, Symbol}; |
9 | 9 | use rustc_span::Span; |
10 | 10 |
|
11 | 11 | use crate::borrow_check::diagnostics::BorrowedContentSource; |
@@ -211,36 +211,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { |
211 | 211 |
|
212 | 212 | // Suggest removing a `&mut` from the use of a mutable reference. |
213 | 213 | 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) => |
244 | 220 | { |
245 | 221 | err.span_label(span, format!("cannot {ACT}", ACT = act)); |
246 | 222 | err.span_label(span, "try removing `&mut` here"); |
@@ -581,6 +557,34 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { |
581 | 557 | } |
582 | 558 | } |
583 | 559 |
|
| 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 | + |
584 | 588 | fn suggest_ampmut_self<'tcx>( |
585 | 589 | tcx: TyCtxt<'tcx>, |
586 | 590 | local_decl: &mir::LocalDecl<'tcx>, |
|
0 commit comments