|
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