Auto merge of #108944 - cjgillot:clear-local-info, r=oli-obk
Wrap the whole LocalInfo in ClearCrossCrate. MIR contains a lot of information about locals. The primary purpose of this information is the quality of borrowck diagnostics. This PR aims to drop this information after MIR analyses are finished, ie. starting from post-cleanup runtime MIR.
This commit is contained in:
commit
511364e787
30 changed files with 188 additions and 214 deletions
|
@ -1985,16 +1985,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
|
||||
let local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
|
||||
match self.body.local_kind(local) {
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
bug!("temporary or return pointer with a name")
|
||||
LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
|
||||
"local variable "
|
||||
}
|
||||
LocalKind::Var => "local variable ",
|
||||
LocalKind::Arg
|
||||
if !self.upvars.is_empty() && local == ty::CAPTURE_STRUCT_LOCAL =>
|
||||
{
|
||||
"variable captured by `move` "
|
||||
}
|
||||
LocalKind::Arg => "function parameter ",
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
bug!("temporary or return pointer with a name")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"local data "
|
||||
|
@ -2008,16 +2010,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
|
||||
let local = root_place.local;
|
||||
match self.body.local_kind(local) {
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
("temporary value".to_string(), "temporary value created here".to_string())
|
||||
}
|
||||
LocalKind::Arg => (
|
||||
"function parameter".to_string(),
|
||||
"function parameter borrowed here".to_string(),
|
||||
),
|
||||
LocalKind::Var => {
|
||||
LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
|
||||
("local binding".to_string(), "local binding introduced here".to_string())
|
||||
}
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
("temporary value".to_string(), "temporary value created here".to_string())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2482,15 +2484,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let (place_description, assigned_span) = match local_decl {
|
||||
Some(LocalDecl {
|
||||
local_info:
|
||||
Some(box LocalInfo::User(
|
||||
ClearCrossCrate::Clear
|
||||
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
ClearCrossCrate::Set(
|
||||
box LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: None,
|
||||
..
|
||||
})),
|
||||
))
|
||||
| Some(box LocalInfo::StaticRef { .. })
|
||||
| None,
|
||||
}))
|
||||
| box LocalInfo::StaticRef { .. }
|
||||
| box LocalInfo::Boring,
|
||||
),
|
||||
..
|
||||
})
|
||||
| None => (self.describe_any_place(place.as_ref()), assigned_span),
|
||||
|
|
|
@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor;
|
|||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::{
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue,
|
||||
Statement, StatementKind, TerminatorKind,
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
|
||||
Rvalue, Statement, StatementKind, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::adjustment::PointerCast;
|
||||
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
||||
|
@ -220,7 +220,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
);
|
||||
err.span_label(body.source_info(drop_loc).span, message);
|
||||
|
||||
if let Some(info) = &local_decl.is_block_tail {
|
||||
if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
|
||||
if info.tail_result_is_ignored {
|
||||
// #85581: If the first mutable borrow's scope contains
|
||||
// the second borrow, this suggestion isn't helpful.
|
||||
|
|
|
@ -196,10 +196,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if self.body.local_decls[local].is_ref_for_guard() {
|
||||
continue;
|
||||
}
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) =
|
||||
&self.body.local_decls[local].local_info
|
||||
if let LocalInfo::StaticRef { def_id, .. } =
|
||||
*self.body.local_decls[local].local_info()
|
||||
{
|
||||
buf.push_str(self.infcx.tcx.item_name(*def_id).as_str());
|
||||
buf.push_str(self.infcx.tcx.item_name(def_id).as_str());
|
||||
ok = Ok(());
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -102,14 +102,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
//
|
||||
// opt_match_place is None for let [mut] x = ... statements,
|
||||
// whether or not the right-hand side is a place expression
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm {
|
||||
opt_match_place: Some((opt_match_place, match_span)),
|
||||
binding_mode: _,
|
||||
opt_ty_info: _,
|
||||
pat_span: _,
|
||||
},
|
||||
)))) = local_decl.local_info
|
||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: Some((opt_match_place, match_span)),
|
||||
binding_mode: _,
|
||||
opt_ty_info: _,
|
||||
pat_span: _,
|
||||
})) = *local_decl.local_info()
|
||||
{
|
||||
let stmt_source_info = self.body.source_info(location);
|
||||
self.append_binding_error(
|
||||
|
@ -478,9 +476,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let mut suggestions: Vec<(Span, String, String)> = Vec::new();
|
||||
for local in binds_to {
|
||||
let bind_to = &self.body.local_decls[*local];
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm { pat_span, .. },
|
||||
)))) = bind_to.local_info
|
||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) =
|
||||
*bind_to.local_info()
|
||||
{
|
||||
let Ok(pat_snippet) =
|
||||
self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{
|
||||
hir::place::PlaceBase,
|
||||
mir::{self, BindingForm, ClearCrossCrate, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
||||
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
||||
};
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
|
@ -105,8 +105,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
reason = String::new();
|
||||
} else {
|
||||
item_msg = access_place_desc;
|
||||
let local_info = &self.body.local_decls[local].local_info;
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
|
||||
let local_info = self.body.local_decls[local].local_info();
|
||||
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
|
||||
let static_name = &self.infcx.tcx.item_name(def_id);
|
||||
reason = format!(", as `{static_name}` is an immutable static item");
|
||||
} else {
|
||||
|
@ -305,15 +305,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
..
|
||||
}) = &self.body[location.block].statements.get(location.statement_index)
|
||||
{
|
||||
match decl.local_info {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
opt_ty_info: Some(sp),
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
},
|
||||
)))) => {
|
||||
match *decl.local_info() {
|
||||
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
opt_ty_info: Some(sp),
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
})) => {
|
||||
if suggest {
|
||||
err.span_note(sp, "the binding is already a mutable borrow");
|
||||
}
|
||||
|
@ -346,10 +344,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
} else if decl.mutability.is_not() {
|
||||
if matches!(
|
||||
decl.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
hir::ImplicitSelfKind::MutRef
|
||||
),)))
|
||||
decl.local_info(),
|
||||
LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef))
|
||||
) {
|
||||
err.note(
|
||||
"as `Self` may be unsized, this call attempts to take `&mut &mut self`",
|
||||
|
@ -482,22 +478,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
match self.local_names[local] {
|
||||
Some(name) if !local_decl.from_compiler_desugaring() => {
|
||||
let label = match local_decl.local_info.as_deref().unwrap() {
|
||||
LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::ImplicitSelf(_),
|
||||
)) => {
|
||||
let label = match *local_decl.local_info() {
|
||||
LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => {
|
||||
let (span, suggestion) =
|
||||
suggest_ampmut_self(self.infcx.tcx, local_decl);
|
||||
Some((true, span, suggestion))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
},
|
||||
))) => {
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
})) => {
|
||||
// check if the RHS is from desugaring
|
||||
let opt_assignment_rhs_span =
|
||||
self.body.find_assignments(local).first().map(|&location| {
|
||||
|
@ -534,16 +526,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
self.infcx.tcx,
|
||||
local_decl,
|
||||
opt_assignment_rhs_span,
|
||||
*opt_ty_info,
|
||||
opt_ty_info,
|
||||
)
|
||||
} else {
|
||||
match local_decl.local_info.as_deref() {
|
||||
Some(LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::Var(mir::VarBindingForm {
|
||||
opt_ty_info: None,
|
||||
..
|
||||
}),
|
||||
))) => {
|
||||
match local_decl.local_info() {
|
||||
LocalInfo::User(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
opt_ty_info: None, ..
|
||||
},
|
||||
)) => {
|
||||
let (span, sugg) = suggest_ampmut_self(
|
||||
self.infcx.tcx,
|
||||
local_decl,
|
||||
|
@ -555,7 +546,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
self.infcx.tcx,
|
||||
local_decl,
|
||||
opt_assignment_rhs_span,
|
||||
*opt_ty_info,
|
||||
opt_ty_info,
|
||||
),
|
||||
}
|
||||
};
|
||||
|
@ -564,21 +555,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
},
|
||||
))) => {
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
})) => {
|
||||
let pattern_span = local_decl.source_info.span;
|
||||
suggest_ref_mut(self.infcx.tcx, pattern_span)
|
||||
.map(|replacement| (true, pattern_span, replacement))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Clear) => {
|
||||
bug!("saw cleared local state")
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -1151,20 +1136,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
pub 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() {
|
||||
match *local_decl.local_info() {
|
||||
// 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)))) => {
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
..
|
||||
})) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
||||
LocalInfo::User(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 == hir::ImplicitSelfKind::MutRef
|
||||
kind == hir::ImplicitSelfKind::MutRef
|
||||
}
|
||||
_ if Some(kw::SelfLower) == local_name => {
|
||||
// Otherwise, check if the name is the `self` keyword - in which case
|
||||
|
|
|
@ -1180,10 +1180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
Some(l)
|
||||
if matches!(
|
||||
body.local_decls[l].local_info,
|
||||
Some(box LocalInfo::AggregateTemp)
|
||||
) =>
|
||||
if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
|
||||
{
|
||||
ConstraintCategory::Usage
|
||||
}
|
||||
|
@ -1684,7 +1681,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
// - maybe we should make that a warning.
|
||||
return;
|
||||
}
|
||||
LocalKind::Var | LocalKind::Temp => {}
|
||||
LocalKind::Temp => {}
|
||||
}
|
||||
|
||||
// When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue