Init local_names lazily for borrowck diagnostics
This commit is contained in:
@@ -71,7 +71,6 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||
) {
|
||||
let tcx = cx.infcx.tcx;
|
||||
let body = cx.body;
|
||||
let local_names = &cx.local_names;
|
||||
|
||||
if let Some(span) = borrow_span {
|
||||
let def_id = body.source.def_id();
|
||||
@@ -220,7 +219,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||
_ => ("destructor", format!("type `{}`", local_decl.ty)),
|
||||
};
|
||||
|
||||
match local_names[dropped_local] {
|
||||
match cx.local_name(dropped_local) {
|
||||
Some(local_name) if !local_decl.from_compiler_desugaring() => {
|
||||
let message = format!(
|
||||
"{borrow_desc}borrow might be used here, when `{local_name}` is dropped \
|
||||
@@ -670,10 +669,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
||||
|
||||
Some(Cause::DropVar(local, location)) => {
|
||||
let mut should_note_order = false;
|
||||
if self.local_names[local].is_some()
|
||||
if self.local_name(local).is_some()
|
||||
&& let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
|
||||
&& let Some(borrowed_local) = place.as_local()
|
||||
&& self.local_names[borrowed_local].is_some()
|
||||
&& self.local_name(borrowed_local).is_some()
|
||||
&& local != borrowed_local
|
||||
{
|
||||
should_note_order = true;
|
||||
@@ -748,7 +747,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(l) = place.as_local() {
|
||||
let local_decl = &self.body.local_decls[l];
|
||||
if self.local_names[l].is_none() {
|
||||
if self.local_name(l).is_none() {
|
||||
local_decl.source_info.span
|
||||
} else {
|
||||
span
|
||||
@@ -793,7 +792,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(l) = place.as_local() {
|
||||
let local_decl = &self.body.local_decls[l];
|
||||
if self.local_names[l].is_none() {
|
||||
if self.local_name(l).is_none() {
|
||||
local_decl.source_info.span
|
||||
} else {
|
||||
span
|
||||
|
||||
@@ -7,17 +7,17 @@ use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify};
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::{self as hir, CoroutineKind, LangItem};
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin};
|
||||
use rustc_infer::traits::SelectionError;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{
|
||||
AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
|
||||
LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement,
|
||||
StatementKind, Terminator, TerminatorKind, find_self_call,
|
||||
StatementKind, Terminator, TerminatorKind, VarDebugInfoContents, find_self_call,
|
||||
};
|
||||
use rustc_middle::ty::print::Print;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveOutIndex};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Spanned;
|
||||
@@ -190,6 +190,36 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> {
|
||||
self.diags_buffer.buffered_move_errors.get(move_out_indices)
|
||||
}
|
||||
|
||||
/// Uses `body.var_debug_info` to find the symbol
|
||||
fn local_name(&self, index: Local) -> Option<Symbol> {
|
||||
*self.local_names().get(index)?
|
||||
}
|
||||
|
||||
fn local_names(&self) -> &IndexSlice<Local, Option<Symbol>> {
|
||||
self.local_names.get_or_init(|| {
|
||||
let mut local_names = IndexVec::from_elem(None, &self.body.local_decls);
|
||||
for var_debug_info in &self.body.var_debug_info {
|
||||
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
|
||||
if let Some(local) = place.as_local() {
|
||||
if let Some(prev_name) = local_names[local]
|
||||
&& var_debug_info.name != prev_name
|
||||
{
|
||||
span_bug!(
|
||||
var_debug_info.source_info.span,
|
||||
"local {:?} has many names (`{}` vs `{}`)",
|
||||
local,
|
||||
prev_name,
|
||||
var_debug_info.name
|
||||
);
|
||||
}
|
||||
local_names[local] = Some(var_debug_info.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
local_names
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
@@ -430,7 +460,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
/// a name, or its name was generated by the compiler, then `Err` is returned
|
||||
fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> {
|
||||
let decl = &self.body.local_decls[local];
|
||||
match self.local_names[local] {
|
||||
match self.local_name(local) {
|
||||
Some(name) if !decl.from_compiler_desugaring() => {
|
||||
buf.push_str(name.as_str());
|
||||
Ok(())
|
||||
@@ -1500,4 +1530,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Skip over locals that begin with an underscore or have no name
|
||||
pub(crate) fn local_excluded_from_unused_mut_lint(&self, index: Local) -> bool {
|
||||
self.local_name(index).is_none_or(|name| name.as_str().starts_with('_'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
|
||||
if let PlaceRef { local, projection: [] } = deref_base {
|
||||
let decl = &self.body.local_decls[local];
|
||||
let local_name = self.local_names[local].map(|sym| format!("`{sym}`"));
|
||||
let local_name = self.local_name(local).map(|sym| format!("`{sym}`"));
|
||||
if decl.is_ref_for_guard() {
|
||||
return self
|
||||
.cannot_move_out_of(
|
||||
@@ -829,7 +829,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
}
|
||||
|
||||
if binds_to.len() == 1 {
|
||||
let place_desc = self.local_names[*local].map(|sym| format!("`{sym}`"));
|
||||
let place_desc = self.local_name(*local).map(|sym| format!("`{sym}`"));
|
||||
|
||||
if let Some(expr) = self.find_expr(binding_span) {
|
||||
self.suggest_cloning(err, bind_to.ty, expr, None);
|
||||
|
||||
@@ -60,7 +60,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
if access_place.as_local().is_some() {
|
||||
reason = ", as it is not declared as mutable".to_string();
|
||||
} else {
|
||||
let name = self.local_names[local].expect("immutable unnamed local");
|
||||
let name = self.local_name(local).expect("immutable unnamed local");
|
||||
reason = format!(", as `{name}` is not declared as mutable");
|
||||
}
|
||||
}
|
||||
@@ -285,7 +285,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
.body
|
||||
.local_decls
|
||||
.get(local)
|
||||
.is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) =>
|
||||
.is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_name(local))) =>
|
||||
{
|
||||
let decl = &self.body.local_decls[local];
|
||||
err.span_label(span, format!("cannot {act}"));
|
||||
@@ -481,7 +481,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let (pointer_sigil, pointer_desc) =
|
||||
if local_decl.ty.is_ref() { ("&", "reference") } else { ("*const", "pointer") };
|
||||
|
||||
match self.local_names[local] {
|
||||
match self.local_name(local) {
|
||||
Some(name) if !local_decl.from_compiler_desugaring() => {
|
||||
err.span_label(
|
||||
span,
|
||||
|
||||
@@ -664,14 +664,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||
self.infcx.tcx,
|
||||
self.body,
|
||||
&self.local_names,
|
||||
&self.local_names(),
|
||||
&self.upvars,
|
||||
errci.fr,
|
||||
);
|
||||
let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||
self.infcx.tcx,
|
||||
self.body,
|
||||
&self.local_names,
|
||||
&self.local_names(),
|
||||
&self.upvars,
|
||||
errci.outlived_fr,
|
||||
);
|
||||
|
||||
@@ -399,7 +399,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
||||
[implicit_inputs + argument_index];
|
||||
let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
|
||||
self.body,
|
||||
&self.local_names,
|
||||
self.local_names(),
|
||||
argument_index,
|
||||
);
|
||||
|
||||
@@ -973,7 +973,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
||||
{
|
||||
let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
|
||||
self.body,
|
||||
&self.local_names,
|
||||
self.local_names(),
|
||||
arg_index,
|
||||
);
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
|
||||
@@ -391,7 +391,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
used_mut_upvars: SmallVec::new(),
|
||||
borrow_set: &borrow_set,
|
||||
upvars: &[],
|
||||
local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
|
||||
local_names: OnceCell::from(IndexVec::from_elem(None, &promoted_body.local_decls)),
|
||||
region_names: RefCell::default(),
|
||||
next_region_name: RefCell::new(1),
|
||||
polonius_output: None,
|
||||
@@ -414,26 +414,6 @@ fn do_mir_borrowck<'tcx>(
|
||||
promoted_mbcx.report_move_errors();
|
||||
}
|
||||
|
||||
let mut local_names = IndexVec::from_elem(None, &body.local_decls);
|
||||
for var_debug_info in &body.var_debug_info {
|
||||
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
|
||||
if let Some(local) = place.as_local() {
|
||||
if let Some(prev_name) = local_names[local]
|
||||
&& var_debug_info.name != prev_name
|
||||
{
|
||||
span_bug!(
|
||||
var_debug_info.source_info.span,
|
||||
"local {:?} has many names (`{}` vs `{}`)",
|
||||
local,
|
||||
prev_name,
|
||||
var_debug_info.name
|
||||
);
|
||||
}
|
||||
local_names[local] = Some(var_debug_info.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut mbcx = MirBorrowckCtxt {
|
||||
root_cx,
|
||||
infcx: &infcx,
|
||||
@@ -450,7 +430,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
used_mut_upvars: SmallVec::new(),
|
||||
borrow_set: &borrow_set,
|
||||
upvars: tcx.closure_captures(def),
|
||||
local_names,
|
||||
local_names: OnceCell::new(),
|
||||
region_names: RefCell::default(),
|
||||
next_region_name: RefCell::new(1),
|
||||
move_errors: Vec::new(),
|
||||
@@ -682,7 +662,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
|
||||
upvars: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
|
||||
|
||||
/// Names of local (user) variables (extracted from `var_debug_info`).
|
||||
local_names: IndexVec<Local, Option<Symbol>>,
|
||||
local_names: OnceCell<IndexVec<Local, Option<Symbol>>>,
|
||||
|
||||
/// Record the region names generated for each region in the given
|
||||
/// MIR def so that we can reuse them later in help/error messages.
|
||||
@@ -2610,7 +2590,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
||||
};
|
||||
|
||||
// Skip over locals that begin with an underscore or have no name
|
||||
if self.local_names[local].is_none_or(|name| name.as_str().starts_with('_')) {
|
||||
if self.local_excluded_from_unused_mut_lint(local) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user