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 98450f5a547da..0400431a542ee 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -1,6 +1,7 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; +use rustc_middle::hir::map::Map; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{ @@ -543,13 +544,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Attempt to search similar mutable associated items for suggestion. // In the future, attempt in all path but initially for RHS of for_loop fn suggest_similar_mut_method_for_for_loop(&self, err: &mut DiagnosticBuilder<'_>) { - let hir = self.infcx.tcx.hir(); - let node = hir.item(self.mir_hir_id()); use hir::{ - Expr, + BodyId, Expr, ExprKind::{Block, Call, DropTemps, Match, MethodCall}, + HirId, ImplItem, ImplItemKind, Item, ItemKind, }; - if let hir::ItemKind::Fn(_, _, body_id) = node.kind { + + fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option { + match hir_map.find(id) { + Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) + | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { + Some(*body_id) + } + _ => None, + } + } + let hir_map = self.infcx.tcx.hir(); + let mir_body_hir_id = self.mir_hir_id(); + if let Some(fn_body_id) = maybe_body_id_of_fn(&hir_map, mir_body_hir_id) { if let Block( hir::Block { expr: @@ -579,7 +591,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. }, _, - ) = hir.body(body_id).value.kind + ) = hir_map.body(fn_body_id).value.kind { let opt_suggestions = path_segment .hir_id diff --git a/src/test/ui/borrowck/issue-82032.rs b/src/test/ui/borrowck/issue-82032.rs new file mode 100644 index 0000000000000..4a01b60c1f62b --- /dev/null +++ b/src/test/ui/borrowck/issue-82032.rs @@ -0,0 +1,16 @@ +use std::{fs, io::*}; +use std::collections::HashMap; + +type Handle = BufWriter; +struct Thing(HashMap); + +impl Thing { + pub fn die_horribly(&mut self) { + for v in self.0.values() { + v.flush(); + //~^ ERROR cannot borrow + } + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-82032.stderr b/src/test/ui/borrowck/issue-82032.stderr new file mode 100644 index 0000000000000..f272477a9f5b3 --- /dev/null +++ b/src/test/ui/borrowck/issue-82032.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference + --> $DIR/issue-82032.rs:10:13 + | +LL | for v in self.0.values() { + | --------------- + | | | + | | help: use mutable method: `values_mut()` + | this iterator yields `&` references +LL | v.flush(); + | ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`.