1
Fork 0

Auto merge of #118316 - Mark-Simulacrum:delete-copy-to-upvars, r=cjgillot

Remove borrowck Upvar duplication

This cuts out an extra allocation and copying over from the already cached closure capture information.
This commit is contained in:
bors 2023-11-26 21:47:19 +00:00
commit 6cf088810f
10 changed files with 35 additions and 50 deletions

View file

@ -217,9 +217,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
projection: place.projection.split_at(index + 1).0, projection: place.projection.split_at(index + 1).0,
}) { }) {
let var_index = field.index(); let var_index = field.index();
buf = self.upvars[var_index].place.to_string(self.infcx.tcx); buf = self.upvars[var_index].to_string(self.infcx.tcx);
ok = Ok(()); ok = Ok(());
if !self.upvars[var_index].by_ref { if !self.upvars[var_index].is_by_ref() {
buf.insert(0, '*'); buf.insert(0, '*');
} }
} else { } else {
@ -250,7 +250,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
local, local,
projection: place.projection.split_at(index + 1).0, projection: place.projection.split_at(index + 1).0,
}) { }) {
buf = self.upvars[field.index()].place.to_string(self.infcx.tcx); buf = self.upvars[field.index()].to_string(self.infcx.tcx);
ok = Ok(()); ok = Ok(());
} else { } else {
let field_name = self.describe_field( let field_name = self.describe_field(

View file

@ -363,8 +363,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
format!("captured variable in an `{closure_kind}` closure"); format!("captured variable in an `{closure_kind}` closure");
let upvar = &self.upvars[upvar_field.unwrap().index()]; let upvar = &self.upvars[upvar_field.unwrap().index()];
let upvar_hir_id = upvar.place.get_root_variable(); let upvar_hir_id = upvar.get_root_variable();
let upvar_name = upvar.place.to_string(self.infcx.tcx); let upvar_name = upvar.to_string(self.infcx.tcx);
let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id); let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
let place_name = self.describe_any_place(move_place.as_ref()); let place_name = self.describe_any_place(move_place.as_ref());

View file

@ -66,7 +66,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
)); ));
let imm_borrow_derefed = self.upvars[upvar_index.index()] let imm_borrow_derefed = self.upvars[upvar_index.index()]
.place
.place .place
.deref_tys() .deref_tys()
.any(|ty| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not))); .any(|ty| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)));
@ -85,7 +84,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if self.is_upvar_field_projection(access_place.as_ref()).is_some() { if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
reason = ", as it is not declared as mutable".to_string(); reason = ", as it is not declared as mutable".to_string();
} else { } else {
let name = self.upvars[upvar_index.index()].place.to_string(self.infcx.tcx); let name = self.upvars[upvar_index.index()].to_string(self.infcx.tcx);
reason = format!(", as `{name}` is not declared as mutable"); reason = format!(", as `{name}` is not declared as mutable");
} }
} }
@ -388,7 +387,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
)); ));
let captured_place = &self.upvars[upvar_index.index()].place; let captured_place = self.upvars[upvar_index.index()];
err.span_label(span, format!("cannot {act}")); err.span_label(span, format!("cannot {act}"));

View file

@ -605,7 +605,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}; };
let captured_place = &self.upvars[upvar_field.index()].place; let captured_place = &self.upvars[upvar_field.index()].place;
let defined_hir = match captured_place.place.base { let defined_hir = match captured_place.base {
PlaceBase::Local(hirid) => Some(hirid), PlaceBase::Local(hirid) => Some(hirid),
PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id), PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id),
_ => None, _ => None,

View file

@ -2,10 +2,9 @@
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
use crate::region_infer::RegionInferenceContext; use crate::region_infer::RegionInferenceContext;
use crate::Upvar;
use rustc_index::IndexSlice; use rustc_index::IndexSlice;
use rustc_middle::mir::{Body, Local}; use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_middle::ty::{self, RegionVid, TyCtxt};
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::Span; use rustc_span::Span;
@ -15,7 +14,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
local_names: &IndexSlice<Local, Option<Symbol>>, local_names: &IndexSlice<Local, Option<Symbol>>,
upvars: &[Upvar<'tcx>], upvars: &[&ty::CapturedPlace<'tcx>],
fr: RegionVid, fr: RegionVid,
) -> Option<(Option<Symbol>, Span)> { ) -> Option<(Option<Symbol>, Span)> {
debug!("get_var_name_and_span_for_region(fr={fr:?})"); debug!("get_var_name_and_span_for_region(fr={fr:?})");
@ -66,10 +65,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn get_upvar_name_and_span_for_region( pub(crate) fn get_upvar_name_and_span_for_region(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
upvars: &[Upvar<'tcx>], upvars: &[&ty::CapturedPlace<'tcx>],
upvar_index: usize, upvar_index: usize,
) -> (Symbol, Span) { ) -> (Symbol, Span) {
let upvar_hir_id = upvars[upvar_index].place.get_root_variable(); let upvar_hir_id = upvars[upvar_index].get_root_variable();
debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}"); debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}");
let upvar_name = tcx.hir().name(upvar_hir_id); let upvar_name = tcx.hir().name(upvar_hir_id);

View file

@ -34,7 +34,7 @@ use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::traits::DefiningAnchor; use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt}; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
use rustc_session::lint::builtin::UNUSED_MUT; use rustc_session::lint::builtin::UNUSED_MUT;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use rustc_target::abi::FieldIdx; use rustc_target::abi::FieldIdx;
@ -99,15 +99,6 @@ use renumber::RegionCtxt;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" } rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
// FIXME(eddyb) perhaps move this somewhere more centrally.
#[derive(Debug)]
struct Upvar<'tcx> {
place: CapturedPlace<'tcx>,
/// If true, the capture is behind a reference.
by_ref: bool,
}
/// Associate some local constants with the `'tcx` lifetime /// Associate some local constants with the `'tcx` lifetime
struct TyCtxtConsts<'tcx>(TyCtxt<'tcx>); struct TyCtxtConsts<'tcx>(TyCtxt<'tcx>);
impl<'tcx> TyCtxtConsts<'tcx> { impl<'tcx> TyCtxtConsts<'tcx> {
@ -192,18 +183,6 @@ fn do_mir_borrowck<'tcx>(
infcx.set_tainted_by_errors(e); infcx.set_tainted_by_errors(e);
errors.set_tainted_by_errors(e); errors.set_tainted_by_errors(e);
} }
let upvars: Vec<_> = tcx
.closure_captures(def)
.iter()
.map(|&captured_place| {
let capture = captured_place.info.capture_kind;
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => true,
};
Upvar { place: captured_place.clone(), by_ref }
})
.collect();
// Replace all regions with fresh inference variables. This // Replace all regions with fresh inference variables. This
// requires first making our own copy of the MIR. This copy will // requires first making our own copy of the MIR. This copy will
@ -253,7 +232,7 @@ fn do_mir_borrowck<'tcx>(
&mut flow_inits, &mut flow_inits,
&mdpe.move_data, &mdpe.move_data,
&borrow_set, &borrow_set,
&upvars, tcx.closure_captures(def),
consumer_options, consumer_options,
); );
@ -323,7 +302,7 @@ fn do_mir_borrowck<'tcx>(
used_mut: Default::default(), used_mut: Default::default(),
used_mut_upvars: SmallVec::new(), used_mut_upvars: SmallVec::new(),
borrow_set: Rc::clone(&borrow_set), borrow_set: Rc::clone(&borrow_set),
upvars: Vec::new(), upvars: &[],
local_names: IndexVec::from_elem(None, &promoted_body.local_decls), local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
region_names: RefCell::default(), region_names: RefCell::default(),
next_region_name: RefCell::new(1), next_region_name: RefCell::new(1),
@ -364,7 +343,7 @@ fn do_mir_borrowck<'tcx>(
used_mut: Default::default(), used_mut: Default::default(),
used_mut_upvars: SmallVec::new(), used_mut_upvars: SmallVec::new(),
borrow_set: Rc::clone(&borrow_set), borrow_set: Rc::clone(&borrow_set),
upvars, upvars: tcx.closure_captures(def),
local_names, local_names,
region_names: RefCell::default(), region_names: RefCell::default(),
next_region_name: RefCell::new(1), next_region_name: RefCell::new(1),
@ -583,7 +562,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
borrow_set: Rc<BorrowSet<'tcx>>, borrow_set: Rc<BorrowSet<'tcx>>,
/// Information about upvars not necessarily preserved in types or MIR /// Information about upvars not necessarily preserved in types or MIR
upvars: Vec<Upvar<'tcx>>, upvars: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
/// Names of local (user) variables (extracted from `var_debug_info`). /// Names of local (user) variables (extracted from `var_debug_info`).
local_names: IndexVec<Local, Option<Symbol>>, local_names: IndexVec<Local, Option<Symbol>>,
@ -2293,7 +2272,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// unique path to the `&mut` // unique path to the `&mut`
hir::Mutability::Mut => { hir::Mutability::Mut => {
let mode = match self.is_upvar_field_projection(place) { let mode = match self.is_upvar_field_projection(place) {
Some(field) if self.upvars[field.index()].by_ref => { Some(field)
if self.upvars[field.index()].is_by_ref() =>
{
is_local_mutation_allowed is_local_mutation_allowed
} }
_ => LocalMutationIsAllowed::Yes, _ => LocalMutationIsAllowed::Yes,
@ -2341,7 +2322,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place={:?}, place_base={:?}", place={:?}, place_base={:?}",
upvar, is_local_mutation_allowed, place, place_base upvar, is_local_mutation_allowed, place, place_base
); );
match (upvar.place.mutability, is_local_mutation_allowed) { match (upvar.mutability, is_local_mutation_allowed) {
( (
Mutability::Not, Mutability::Not,
LocalMutationIsAllowed::No LocalMutationIsAllowed::No

View file

@ -37,7 +37,7 @@ use crate::{
renumber, renumber,
type_check::{self, MirTypeckRegionConstraints, MirTypeckResults}, type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
universal_regions::UniversalRegions, universal_regions::UniversalRegions,
BorrowckInferCtxt, Upvar, BorrowckInferCtxt,
}; };
pub type PoloniusOutput = Output<RustcFacts>; pub type PoloniusOutput = Output<RustcFacts>;
@ -166,7 +166,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>, flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>, borrow_set: &BorrowSet<'tcx>,
upvars: &[Upvar<'tcx>], upvars: &[&ty::CapturedPlace<'tcx>],
consumer_options: Option<ConsumerOptions>, consumer_options: Option<ConsumerOptions>,
) -> NllOutput<'tcx> { ) -> NllOutput<'tcx> {
let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled(); let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();

View file

@ -4,7 +4,6 @@ use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
use crate::places_conflict; use crate::places_conflict;
use crate::AccessDepth; use crate::AccessDepth;
use crate::BorrowIndex; use crate::BorrowIndex;
use crate::Upvar;
use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::mir::BorrowKind; use rustc_middle::mir::BorrowKind;
use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem}; use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem};
@ -150,7 +149,7 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool {
/// of a closure type. /// of a closure type.
pub(crate) fn is_upvar_field_projection<'tcx>( pub(crate) fn is_upvar_field_projection<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
upvars: &[Upvar<'tcx>], upvars: &[&rustc_middle::ty::CapturedPlace<'tcx>],
place_ref: PlaceRef<'tcx>, place_ref: PlaceRef<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
) -> Option<FieldIdx> { ) -> Option<FieldIdx> {
@ -166,7 +165,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>(
Some((place_base, ProjectionElem::Field(field, _ty))) => { Some((place_base, ProjectionElem::Field(field, _ty))) => {
let base_ty = place_base.ty(body, tcx).ty; let base_ty = place_base.ty(body, tcx).ty;
if (base_ty.is_closure() || base_ty.is_coroutine()) if (base_ty.is_closure() || base_ty.is_coroutine())
&& (!by_ref || upvars[field.index()].by_ref) && (!by_ref || upvars[field.index()].is_by_ref())
{ {
Some(field) Some(field)
} else { } else {

View file

@ -68,7 +68,7 @@ use crate::{
region_infer::TypeTest, region_infer::TypeTest,
type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
universal_regions::{DefiningTy, UniversalRegions}, universal_regions::{DefiningTy, UniversalRegions},
BorrowckInferCtxt, Upvar, BorrowckInferCtxt,
}; };
macro_rules! span_mirbug { macro_rules! span_mirbug {
@ -138,7 +138,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
elements: &Rc<RegionValueElements>, elements: &Rc<RegionValueElements>,
upvars: &[Upvar<'tcx>], upvars: &[&ty::CapturedPlace<'tcx>],
use_polonius: bool, use_polonius: bool,
) -> MirTypeckResults<'tcx> { ) -> MirTypeckResults<'tcx> {
let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
@ -857,7 +857,7 @@ struct BorrowCheckContext<'a, 'tcx> {
all_facts: &'a mut Option<AllFacts>, all_facts: &'a mut Option<AllFacts>,
borrow_set: &'a BorrowSet<'tcx>, borrow_set: &'a BorrowSet<'tcx>,
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>, pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
upvars: &'a [Upvar<'tcx>], upvars: &'a [&'a ty::CapturedPlace<'tcx>],
/// The set of loans that are live at a given point in the CFG, filled in by `liveness::trace`, /// The set of loans that are live at a given point in the CFG, filled in by `liveness::trace`,
/// when using `-Zpolonius=next`. /// when using `-Zpolonius=next`.

View file

@ -247,6 +247,13 @@ impl<'tcx> CapturedPlace<'tcx> {
.span .span
} }
} }
pub fn is_by_ref(&self) -> bool {
match self.info.capture_kind {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => true,
}
}
} }
#[derive(Copy, Clone, Debug, HashStable)] #[derive(Copy, Clone, Debug, HashStable)]