Remove PlaceBase enum and make Place base field be local: Local

This commit is contained in:
Santiago Pastorino 2019-12-11 16:50:03 -03:00 committed by Oliver Scherer
parent fd5aa32c35
commit 5d9b399044
50 changed files with 456 additions and 656 deletions

View file

@ -1655,7 +1655,7 @@ impl Debug for Statement<'_> {
/// changing or disturbing program state.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
pub struct Place<'tcx> {
pub base: PlaceBase,
pub local: Local,
/// projection out of a place (access a field, deref a pointer, etc)
pub projection: &'tcx List<PlaceElem<'tcx>>,
@ -1663,12 +1663,6 @@ pub struct Place<'tcx> {
impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)]
pub enum PlaceBase {
/// local variable
Local(Local),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(RustcEncodable, RustcDecodable, HashStable)]
pub enum ProjectionElem<V, T> {
@ -1756,14 +1750,14 @@ rustc_index::newtype_index! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PlaceRef<'a, 'tcx> {
pub base: &'a PlaceBase,
pub local: &'a Local,
pub projection: &'a [PlaceElem<'tcx>],
}
impl<'tcx> Place<'tcx> {
// FIXME change this to a const fn by also making List::empty a const fn.
pub fn return_place() -> Place<'tcx> {
Place { base: PlaceBase::Local(RETURN_PLACE), projection: List::empty() }
Place { local: RETURN_PLACE, projection: List::empty() }
}
/// Returns `true` if this `Place` contains a `Deref` projection.
@ -1780,10 +1774,8 @@ impl<'tcx> Place<'tcx> {
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub fn local_or_deref_local(&self) -> Option<Local> {
match self.as_ref() {
PlaceRef { base: &PlaceBase::Local(local), projection: &[] }
| PlaceRef { base: &PlaceBase::Local(local), projection: &[ProjectionElem::Deref] } => {
Some(local)
}
PlaceRef { local, projection: &[] }
| PlaceRef { local, projection: &[ProjectionElem::Deref] } => Some(*local),
_ => None,
}
}
@ -1795,19 +1787,13 @@ impl<'tcx> Place<'tcx> {
}
pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
PlaceRef { base: &self.base, projection: &self.projection }
PlaceRef { local: &self.local, projection: &self.projection }
}
}
impl From<Local> for Place<'_> {
fn from(local: Local) -> Self {
Place { base: local.into(), projection: List::empty() }
}
}
impl From<Local> for PlaceBase {
fn from(local: Local) -> Self {
PlaceBase::Local(local)
Place { local: local.into(), projection: List::empty() }
}
}
@ -1818,10 +1804,8 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub fn local_or_deref_local(&self) -> Option<Local> {
match self {
PlaceRef { base: PlaceBase::Local(local), projection: [] }
| PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] } => {
Some(*local)
}
PlaceRef { local, projection: [] }
| PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(**local),
_ => None,
}
}
@ -1830,7 +1814,7 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
/// projections, return `Some(_X)`.
pub fn as_local(&self) -> Option<Local> {
match self {
PlaceRef { base: PlaceBase::Local(l), projection: [] } => Some(*l),
PlaceRef { local, projection: [] } => Some(**local),
_ => None,
}
}
@ -1852,7 +1836,7 @@ impl Debug for Place<'_> {
}
}
write!(fmt, "{:?}", self.base)?;
write!(fmt, "{:?}", self.local)?;
for elem in self.projection.iter() {
match elem {
@ -1896,14 +1880,6 @@ impl Debug for Place<'_> {
}
}
impl Debug for PlaceBase {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
match *self {
PlaceBase::Local(id) => write!(fmt, "{:?}", id),
}
}
}
///////////////////////////////////////////////////////////////////////////
// Scopes
@ -2964,25 +2940,11 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Place { base: self.base.fold_with(folder), projection: self.projection.fold_with(folder) }
Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.base.visit_with(visitor) || self.projection.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for PlaceBase {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
match self {
PlaceBase::Local(local) => PlaceBase::Local(local.fold_with(folder)),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match self {
PlaceBase::Local(local) => local.visit_with(visitor),
}
self.local.visit_with(visitor) || self.projection.visit_with(visitor)
}
}

View file

@ -114,7 +114,7 @@ impl<'tcx> PlaceTy<'tcx> {
impl<'tcx> Place<'tcx> {
pub fn ty_from<D>(
base: &PlaceBase,
local: &Local,
projection: &[PlaceElem<'tcx>],
local_decls: &D,
tcx: TyCtxt<'tcx>,
@ -124,25 +124,16 @@ impl<'tcx> Place<'tcx> {
{
projection
.iter()
.fold(base.ty(local_decls), |place_ty, elem| place_ty.projection_ty(tcx, elem))
.fold(PlaceTy::from_ty(local_decls.local_decls()[*local].ty), |place_ty, elem| {
place_ty.projection_ty(tcx, elem)
})
}
pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
where
D: HasLocalDecls<'tcx>,
{
Place::ty_from(&self.base, &self.projection, local_decls, tcx)
}
}
impl<'tcx> PlaceBase {
pub fn ty<D>(&self, local_decls: &D) -> PlaceTy<'tcx>
where
D: HasLocalDecls<'tcx>,
{
match self {
PlaceBase::Local(index) => PlaceTy::from_ty(local_decls.local_decls()[*index].ty),
}
Place::ty_from(&self.local, &self.projection, local_decls, tcx)
}
}

View file

@ -164,10 +164,10 @@ macro_rules! make_mir_visitor {
}
fn visit_place_base(&mut self,
base: & $($mutability)? PlaceBase,
local: & $($mutability)? Local,
context: PlaceContext,
location: Location) {
self.super_place_base(base, context, location);
self.super_place_base(local, context, location);
}
visit_place_fns!($($mutability)?);
@ -705,14 +705,10 @@ macro_rules! make_mir_visitor {
}
fn super_place_base(&mut self,
place_base: & $($mutability)? PlaceBase,
local: & $($mutability)? Local,
context: PlaceContext,
location: Location) {
match place_base {
PlaceBase::Local(local) => {
self.visit_local(local, context, location);
}
}
self.visit_local(local, context, location);
}
fn super_local_decl(&mut self,
@ -845,7 +841,7 @@ macro_rules! visit_place_fns {
context: PlaceContext,
location: Location,
) {
self.visit_place_base(&mut place.base, context, location);
self.visit_place_base(&mut place.local, context, location);
if let Some(new_projection) = self.process_projection(&place.projection) {
place.projection = self.tcx().intern_place_elems(&new_projection);
@ -886,23 +882,23 @@ macro_rules! visit_place_fns {
() => (
fn visit_projection(
&mut self,
base: &PlaceBase,
local: &Local,
projection: &[PlaceElem<'tcx>],
context: PlaceContext,
location: Location,
) {
self.super_projection(base, projection, context, location);
self.super_projection(local, projection, context, location);
}
fn visit_projection_elem(
&mut self,
base: &PlaceBase,
local: &Local,
proj_base: &[PlaceElem<'tcx>],
elem: &PlaceElem<'tcx>,
context: PlaceContext,
location: Location,
) {
self.super_projection_elem(base, proj_base, elem, context, location);
self.super_projection_elem(local, proj_base, elem, context, location);
}
fn super_place(
@ -921,9 +917,9 @@ macro_rules! visit_place_fns {
};
}
self.visit_place_base(&place.base, context, location);
self.visit_place_base(&place.local, context, location);
self.visit_projection(&place.base,
self.visit_projection(&place.local,
&place.projection,
context,
location);
@ -931,7 +927,7 @@ macro_rules! visit_place_fns {
fn super_projection(
&mut self,
base: &PlaceBase,
local: &Local,
projection: &[PlaceElem<'tcx>],
context: PlaceContext,
location: Location,
@ -939,13 +935,13 @@ macro_rules! visit_place_fns {
let mut cursor = projection;
while let [proj_base @ .., elem] = cursor {
cursor = proj_base;
self.visit_projection_elem(base, cursor, elem, context, location);
self.visit_projection_elem(local, cursor, elem, context, location);
}
}
fn super_projection_elem(
&mut self,
_base: &PlaceBase,
_local: &Local,
_proj_base: &[PlaceElem<'tcx>],
elem: &PlaceElem<'tcx>,
_context: PlaceContext,

View file

@ -226,11 +226,11 @@ pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
where
D: TyDecoder<'tcx>,
{
let base: mir::PlaceBase = Decodable::decode(decoder)?;
let local: mir::Local = Decodable::decode(decoder)?;
let len = decoder.read_usize()?;
let projection: &'tcx List<mir::PlaceElem<'tcx>> =
decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
Ok(mir::Place { base, projection })
Ok(mir::Place { local, projection })
}
#[inline]

View file

@ -2434,7 +2434,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut projection = place.projection.to_vec();
projection.push(elem);
Place { base: place.base, projection: self.intern_place_elems(&projection) }
Place { local: place.local, projection: self.intern_place_elems(&projection) }
}
pub fn intern_existential_predicates(

View file

@ -1286,9 +1286,9 @@ fn generator_layout_and_saved_local_names(
let generator_layout = body.generator_layout.as_ref().unwrap();
let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
let state_arg = mir::PlaceBase::Local(mir::Local::new(1));
let state_arg = mir::Local::new(1);
for var in &body.var_debug_info {
if var.place.base != state_arg {
if var.place.local != state_arg {
continue;
}
match var.place.projection[..] {

View file

@ -128,17 +128,13 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
};
if is_consume {
let base_ty =
mir::Place::ty_from(place_ref.base, proj_base, *self.fx.mir, cx.tcx());
mir::Place::ty_from(place_ref.local, proj_base, *self.fx.mir, cx.tcx());
let base_ty = self.fx.monomorphize(&base_ty);
// ZSTs don't require any actual memory access.
let elem_ty = base_ty.projection_ty(cx.tcx(), elem).ty;
let elem_ty = self.fx.monomorphize(&elem_ty);
let span = match place_ref.base {
mir::PlaceBase::Local(index) => {
self.fx.mir.local_decls[*index].source_info.span
}
};
let span = self.fx.mir.local_decls[*place_ref.local].source_info.span;
if cx.spanned_layout_of(elem_ty, span).is_zst() {
return;
}
@ -178,9 +174,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
// We use `NonUseContext::VarDebugInfo` for the base,
// which might not force the base local to memory,
// so we have to do it manually.
match place_ref.base {
mir::PlaceBase::Local(local) => self.visit_local(&local, context, location),
}
self.visit_local(place_ref.local, context, location);
}
}
@ -191,7 +185,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
}
self.process_place(
&mir::PlaceRef { base: place_ref.base, projection: proj_base },
&mir::PlaceRef { local: place_ref.local, projection: proj_base },
base_context,
location,
);
@ -218,8 +212,8 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
};
}
self.visit_place_base(place_ref.base, context, location);
self.visit_projection(place_ref.base, place_ref.projection, context, location);
self.visit_place_base(place_ref.local, context, location);
self.visit_projection(place_ref.local, place_ref.projection, context, location);
}
}
}

View file

@ -1109,7 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
self.codegen_place(
bx,
&mir::PlaceRef { base: &dest.base, projection: &dest.projection },
&mir::PlaceRef { local: &dest.local, projection: &dest.projection },
)
};
if fn_ret.is_indirect() {

View file

@ -258,9 +258,7 @@ pub fn per_local_var_debug_info(
if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() {
let mut per_local = IndexVec::from_elem(vec![], &body.local_decls);
for var in &body.var_debug_info {
match var.place.base {
mir::PlaceBase::Local(local) => per_local[local].push(var),
}
per_local[var.place.local].push(var);
}
Some(per_local)
} else {

View file

@ -373,43 +373,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Option<OperandRef<'tcx, Bx::Value>> {
debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
match place_ref.base {
mir::PlaceBase::Local(index) => {
match self.locals[*index] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for elem in place_ref.projection.iter() {
match elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_)
| mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
}
_ => return None,
match self.locals[*place_ref.local] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for elem in place_ref.projection.iter() {
match elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_)
| mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
}
Some(o)
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place_ref);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
_ => return None,
}
}
Some(o)
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place_ref);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
}
}
}

View file

@ -415,28 +415,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let tcx = self.cx.tcx();
let result = match place_ref {
mir::PlaceRef { base: mir::PlaceBase::Local(index), projection: [] } => {
match self.locals[*index] {
LocalRef::Place(place) => {
return place;
}
LocalRef::UnsizedPlace(place) => {
return bx.load_operand(place).deref(cx);
}
LocalRef::Operand(..) => {
bug!("using operand local {:?} as place", place_ref);
}
mir::PlaceRef { local, projection: [] } => match self.locals[**local] {
LocalRef::Place(place) => {
return place;
}
}
mir::PlaceRef { base, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
LocalRef::UnsizedPlace(place) => {
return bx.load_operand(place).deref(cx);
}
LocalRef::Operand(..) => {
bug!("using operand local {:?} as place", place_ref);
}
},
mir::PlaceRef { local, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
// Load the pointer from its location.
self.codegen_consume(bx, &mir::PlaceRef { base, projection: proj_base })
self.codegen_consume(bx, &mir::PlaceRef { local, projection: proj_base })
.deref(bx.cx())
}
mir::PlaceRef { base, projection: [proj_base @ .., elem] } => {
mir::PlaceRef { local, projection: [proj_base @ .., elem] } => {
// FIXME turn this recursion into iteration
let cg_base =
self.codegen_place(bx, &mir::PlaceRef { base, projection: proj_base });
self.codegen_place(bx, &mir::PlaceRef { local, projection: proj_base });
match elem {
mir::ProjectionElem::Deref => bug!(),
@ -501,7 +499,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
let tcx = self.cx.tcx();
let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, *self.mir, tcx);
let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
self.monomorphize(&place_ty.ty)
}
}

View file

@ -208,11 +208,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx);
match borrowed_place.base {
mir::PlaceBase::Local(local) => {
self.local_map.entry(local).or_default().insert(idx);
}
}
self.local_map.entry(borrowed_place.local).or_default().insert(idx);
}
self.super_assign(assigned_place, rvalue, location)

View file

@ -2,8 +2,8 @@ use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
use rustc::mir::{
BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, PlaceRef, ProjectionElem,
Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue,
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::subst::SubstsRef;
@ -188,11 +188,8 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
// of the borrows are killed: the ones whose `borrowed_place`
// conflicts with the `place`.
match place.as_ref() {
PlaceRef { base: &PlaceBase::Local(local), projection: &[] }
| PlaceRef {
base: &PlaceBase::Local(local),
projection: &[ProjectionElem::Deref],
} => {
PlaceRef { local, projection: &[] }
| PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
debug!(
"Recording `killed` facts for borrows of local={:?} at location={:?}",
local, location
@ -202,12 +199,12 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
all_facts,
self.borrow_set,
self.location_table,
&local,
local,
location,
);
}
PlaceRef { base: &PlaceBase::Local(local), projection: &[.., _] } => {
PlaceRef { local, projection: &[.., _] } => {
// Kill conflicting borrows of the innermost local.
debug!(
"Recording `killed` facts for borrows of \
@ -215,7 +212,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
local, location
);
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
for &borrow_index in borrow_indices {
let places_conflict = places_conflict::places_conflict(
self.infcx.tcx,

View file

@ -1,7 +1,7 @@
use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceBase,
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
};
use rustc::traits::error_reporting::suggest_constraining_type_param;
use rustc::ty::{self, Ty};
@ -186,7 +186,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
let ty =
Place::ty_from(used_place.base, used_place.projection, *self.body, self.infcx.tcx)
Place::ty_from(used_place.local, used_place.projection, *self.body, self.infcx.tcx)
.ty;
let needs_note = match ty.kind {
ty::Closure(id, _) => {
@ -597,15 +597,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// field access to a union. If we find that, then we will keep the place of the
// union being accessed and the field that was being accessed so we can check the
// second borrowed place for the same union and a access to a different field.
let Place { base, projection } = first_borrowed_place;
let Place { local, projection } = first_borrowed_place;
let mut cursor = projection.as_ref();
while let [proj_base @ .., elem] = cursor {
cursor = proj_base;
match elem {
ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => {
return Some((PlaceRef { base: base, projection: proj_base }, field));
ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
return Some((PlaceRef { local, projection: proj_base }, field));
}
_ => {}
}
@ -615,21 +615,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.and_then(|(target_base, target_field)| {
// With the place of a union and a field access into it, we traverse the second
// borrowed place and look for a access to a different field of the same union.
let Place { base, projection } = second_borrowed_place;
let Place { local, projection } = second_borrowed_place;
let mut cursor = projection.as_ref();
while let [proj_base @ .., elem] = cursor {
cursor = proj_base;
if let ProjectionElem::Field(field, _) = elem {
if let Some(union_ty) = union_ty(base, proj_base) {
if let Some(union_ty) = union_ty(local, proj_base) {
if field != target_field
&& base == target_base.base
&& local == target_base.local
&& proj_base == target_base.projection
{
// FIXME when we avoid clone reuse describe_place closure
let describe_base_place = self
.describe_place(PlaceRef { base: base, projection: proj_base })
.describe_place(PlaceRef { local, projection: proj_base })
.unwrap_or_else(|| "_".to_owned());
return Some((
@ -686,14 +686,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let borrow_span = borrow_spans.var_or_use();
assert!(root_place.projection.is_empty());
let proper_span = match root_place.base {
PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span,
};
let proper_span = self.body.local_decls[*root_place.local].source_info.span;
let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
if self.access_place_error_reported.contains(&(
Place { base: root_place.base.clone(), projection: root_place_projection },
Place { local: root_place.local.clone(), projection: root_place_projection },
borrow_span,
)) {
debug!(
@ -704,22 +702,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
self.access_place_error_reported.insert((
Place { base: root_place.base.clone(), projection: root_place_projection },
Place { local: root_place.local.clone(), projection: root_place_projection },
borrow_span,
));
match borrow.borrowed_place.base {
PlaceBase::Local(local) => {
if self.body.local_decls[local].is_ref_to_thread_local() {
let err = self.report_thread_local_value_does_not_live_long_enough(
drop_span,
borrow_span,
);
err.buffer(&mut self.errors_buffer);
return;
}
}
};
let borrowed_local = borrow.borrowed_place.local;
if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
let err =
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
err.buffer(&mut self.errors_buffer);
return;
}
if let StorageDeadOrDrop::Destructor(dropped_ty) =
self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
@ -1145,12 +1138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
let root_place =
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
let local =
if let PlaceRef { base: PlaceBase::Local(local), projection: [] } = root_place {
local
} else {
bug!("try_report_cannot_return_reference_to_local: not a local")
};
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())
@ -1517,7 +1505,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
[proj_base @ .., elem] => {
// FIXME(spastorino) make this iterate
let base_access = self.classify_drop_access_kind(PlaceRef {
base: place.base,
local: place.local,
projection: proj_base,
});
match elem {
@ -1525,7 +1513,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
StorageDeadOrDrop::LocalStorageDead
| StorageDeadOrDrop::BoxedStorageDead => {
assert!(
Place::ty_from(&place.base, proj_base, *self.body, tcx).ty.is_box(),
Place::ty_from(&place.local, proj_base, *self.body, tcx)
.ty
.is_box(),
"Drop of value behind a reference or raw pointer"
);
StorageDeadOrDrop::BoxedStorageDead
@ -1533,7 +1523,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
StorageDeadOrDrop::Destructor(_) => base_access,
},
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
let base_ty = Place::ty_from(&place.base, proj_base, *self.body, tcx).ty;
let base_ty = Place::ty_from(&place.local, proj_base, *self.body, tcx).ty;
match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor

View file

@ -2,8 +2,7 @@
use rustc::mir::{
AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind,
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
};
use rustc::ty::layout::VariantIdx;
use rustc::ty::print::Print;
@ -169,30 +168,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match place {
PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
PlaceRef { local, projection: [] } => {
self.append_local_to_string(*local, buf)?;
}
PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
if self.body.local_decls[local].is_ref_for_guard() =>
PlaceRef { local, projection: [ProjectionElem::Deref] }
if self.body.local_decls[*local].is_ref_for_guard() =>
{
self.append_place_to_string(
PlaceRef { base: &PlaceBase::Local(local), projection: &[] },
PlaceRef { local: local, projection: &[] },
buf,
autoderef,
&including_downcast,
)?;
}
PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
if self.body.local_decls[local].is_ref_to_static() =>
PlaceRef { local, projection: [ProjectionElem::Deref] }
if self.body.local_decls[*local].is_ref_to_static() =>
{
let local_info = &self.body.local_decls[local].local_info;
let local_info = &self.body.local_decls[*local].local_info;
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
} else {
unreachable!();
}
}
PlaceRef { base, projection: [proj_base @ .., elem] } => {
PlaceRef { local, projection: [proj_base @ .., elem] } => {
match elem {
ProjectionElem::Deref => {
let upvar_field_projection = self.is_upvar_field_projection(place);
@ -208,29 +207,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if autoderef {
// FIXME turn this recursion into iteration
self.append_place_to_string(
PlaceRef { base, projection: proj_base },
PlaceRef { local, projection: proj_base },
buf,
autoderef,
&including_downcast,
)?;
} else {
match (proj_base, base) {
_ => {
buf.push_str(&"*");
self.append_place_to_string(
PlaceRef { base, projection: proj_base },
buf,
autoderef,
&including_downcast,
)?;
}
}
buf.push_str(&"*");
self.append_place_to_string(
PlaceRef { local, projection: proj_base },
buf,
autoderef,
&including_downcast,
)?;
}
}
}
ProjectionElem::Downcast(..) => {
self.append_place_to_string(
PlaceRef { base, projection: proj_base },
PlaceRef { local, projection: proj_base },
buf,
autoderef,
&including_downcast,
@ -249,9 +244,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
buf.push_str(&name);
} else {
let field_name = self
.describe_field(PlaceRef { base, projection: proj_base }, *field);
.describe_field(PlaceRef { local, projection: proj_base }, *field);
self.append_place_to_string(
PlaceRef { base, projection: proj_base },
PlaceRef { local, projection: proj_base },
buf,
autoderef,
&including_downcast,
@ -263,7 +258,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
autoderef = true;
self.append_place_to_string(
PlaceRef { base, projection: proj_base },
PlaceRef { local, projection: proj_base },
buf,
autoderef,
&including_downcast,
@ -280,7 +275,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// then use another while the borrow is held, don't output indices details
// to avoid confusing the end-user
self.append_place_to_string(
PlaceRef { base, projection: proj_base },
PlaceRef { local, projection: proj_base },
buf,
autoderef,
&including_downcast,
@ -311,17 +306,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
// FIXME Place2 Make this work iteratively
match place {
PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
PlaceRef { local, projection: [] } => {
let local = &self.body.local_decls[*local];
self.describe_field_from_ty(&local.ty, field, None)
}
PlaceRef { base, projection: [proj_base @ .., elem] } => match elem {
PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
ProjectionElem::Deref => {
self.describe_field(PlaceRef { base, projection: proj_base }, field)
self.describe_field(PlaceRef { local, projection: proj_base }, field)
}
ProjectionElem::Downcast(_, variant_index) => {
let base_ty =
Place::ty_from(place.base, place.projection, *self.body, self.infcx.tcx).ty;
Place::ty_from(place.local, place.projection, *self.body, self.infcx.tcx)
.ty;
self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
}
ProjectionElem::Field(_, field_type) => {
@ -330,7 +326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
self.describe_field(PlaceRef { base, projection: proj_base }, field)
self.describe_field(PlaceRef { local, projection: proj_base }, field)
}
},
}
@ -451,7 +447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// If we didn't find an overloaded deref or index, then assume it's a
// built in deref and check the type of the base.
let base_ty = Place::ty_from(deref_base.base, deref_base.projection, *self.body, tcx).ty;
let base_ty = Place::ty_from(deref_base.local, deref_base.projection, *self.body, tcx).ty;
if base_ty.is_unsafe_ptr() {
BorrowedContentSource::DerefRawPointer
} else if base_ty.is_mutable_ptr() {

View file

@ -273,7 +273,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let description = if place.projection.len() == 1 {
format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
} else {
let base_static = PlaceRef { base: &place.base, projection: &[ProjectionElem::Deref] };
let base_static =
PlaceRef { local: &place.local, projection: &[ProjectionElem::Deref] };
format!(
"`{:?}` as `{:?}` is a static item",
@ -302,12 +303,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let deref_base = match deref_target_place.projection.as_ref() {
&[ref proj_base @ .., ProjectionElem::Deref] => {
PlaceRef { base: &deref_target_place.base, projection: &proj_base }
PlaceRef { local: &deref_target_place.local, projection: &proj_base }
}
_ => bug!("deref_target_place is not a deref projection"),
};
if let PlaceRef { base: PlaceBase::Local(local), projection: [] } = deref_base {
if let PlaceRef { local, projection: [] } = deref_base {
let decl = &self.body.local_decls[*local];
if decl.is_ref_for_guard() {
let mut err = self.cannot_move_out_of(

View file

@ -1,5 +1,5 @@
use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache};
use rustc::mir::{Mutability, Place, PlaceBase, PlaceRef, ProjectionElem};
use rustc::mir::{Mutability, Place, PlaceRef, ProjectionElem};
use rustc::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_hir::Node;
@ -42,7 +42,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
match the_place_err {
PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
PlaceRef { local, projection: [] } => {
item_msg = format!("`{}`", access_place_desc.unwrap());
if access_place.as_local().is_some() {
reason = ", as it is not declared as mutable".to_string();
@ -53,11 +53,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
PlaceRef {
base: _,
local,
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => {
debug_assert!(is_closure_or_generator(
Place::ty_from(&the_place_err.base, proj_base, *self.body, self.infcx.tcx).ty
Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty
));
item_msg = format!("`{}`", access_place_desc.unwrap());
@ -69,21 +69,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
if self.body.local_decls[local].is_ref_for_guard() =>
PlaceRef { local, projection: [ProjectionElem::Deref] }
if self.body.local_decls[*local].is_ref_for_guard() =>
{
item_msg = format!("`{}`", access_place_desc.unwrap());
reason = ", as it is immutable for the pattern guard".to_string();
}
PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
if self.body.local_decls[local].is_ref_to_static() =>
PlaceRef { local, projection: [ProjectionElem::Deref] }
if self.body.local_decls[*local].is_ref_to_static() =>
{
if access_place.projection.len() == 1 {
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
reason = String::new();
} else {
item_msg = format!("`{}`", access_place_desc.unwrap());
let local_info = &self.body.local_decls[local].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 `{}` is an immutable static item", static_name);
@ -92,8 +92,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
}
PlaceRef { base: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
if the_place_err.base == &PlaceBase::Local(Local::new(1))
PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
if *the_place_err.local == Local::new(1)
&& proj_base.is_empty()
&& !self.upvars.is_empty()
{
@ -101,7 +101,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr());
debug_assert!(is_closure_or_generator(
Place::ty_from(
the_place_err.base,
the_place_err.local,
the_place_err.projection,
*self.body,
self.infcx.tcx
@ -116,7 +116,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
} else {
let source = self.borrowed_content_source(PlaceRef {
base: the_place_err.base,
local: the_place_err.local,
projection: proj_base,
});
let pointer_type = source.describe_for_immutable_place();
@ -136,10 +136,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
PlaceRef { base: _, projection: [.., ProjectionElem::Index(_)] }
| PlaceRef { base: _, projection: [.., ProjectionElem::ConstantIndex { .. }] }
| PlaceRef { base: _, projection: [.., ProjectionElem::Subslice { .. }] }
| PlaceRef { base: _, projection: [.., ProjectionElem::Downcast(..)] } => {
PlaceRef { local: _, projection: [.., ProjectionElem::Index(_)] }
| PlaceRef { local: _, projection: [.., ProjectionElem::ConstantIndex { .. }] }
| PlaceRef { local: _, projection: [.., ProjectionElem::Subslice { .. }] }
| PlaceRef { local: _, projection: [.., ProjectionElem::Downcast(..)] } => {
bug!("Unexpected immutable place.")
}
}
@ -187,7 +187,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// struct we've got a field access of (it must be a reference since there's a deref
// after the field access).
PlaceRef {
base,
local,
projection:
[proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref],
} => {
@ -195,7 +195,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some((span, message)) = annotate_struct_field(
self.infcx.tcx,
Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty,
Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty,
field,
) {
err.span_suggestion(
@ -208,7 +208,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
// Suggest removing a `&mut` from the use of a mutable reference.
PlaceRef { base: PlaceBase::Local(local), projection: [] }
PlaceRef { local, projection: [] }
if {
self.body
.local_decls
@ -246,7 +246,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// We want to suggest users use `let mut` for local (user
// variable) mutations...
PlaceRef { base: PlaceBase::Local(local), projection: [] }
PlaceRef { local, projection: [] }
if self.body.local_decls[*local].can_be_made_mutable() =>
{
// ... but it doesn't make sense to suggest it on
@ -267,11 +267,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Also suggest adding mut for upvars
PlaceRef {
base,
local,
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => {
debug_assert!(is_closure_or_generator(
Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty
Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty
));
err.span_label(span, format!("cannot {ACT}", ACT = act));
@ -298,7 +298,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// complete hack to approximate old AST-borrowck
// diagnostic: if the span starts with a mutable borrow of
// a local variable, then just suggest the user remove it.
PlaceRef { base: PlaceBase::Local(_), projection: [] }
PlaceRef { local: _, projection: [] }
if {
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
snippet.starts_with("&mut ")
@ -311,7 +311,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.span_label(span, "try removing `&mut` here");
}
PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
PlaceRef { local, projection: [ProjectionElem::Deref] }
if self.body.local_decls[*local].is_ref_for_guard() =>
{
err.span_label(span, format!("cannot {ACT}", ACT = act));
@ -325,7 +325,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
//
// FIXME: can this case be generalized to work for an
// arbitrary base for the projection?
PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
PlaceRef { local, projection: [ProjectionElem::Deref] }
if self.body.local_decls[*local].is_user_variable() =>
{
let local_decl = &self.body.local_decls[*local];
@ -408,10 +408,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
PlaceRef {
base,
local,
projection: [ProjectionElem::Deref],
// FIXME document what is this 1 magic number about
} if *base == PlaceBase::Local(Local::new(1)) && !self.upvars.is_empty() => {
} if *local == Local::new(1) && !self.upvars.is_empty() => {
err.span_label(span, format!("cannot {ACT}", ACT = act));
err.span_help(
self.body.span,
@ -419,7 +419,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
);
}
PlaceRef { base: _, projection: [.., ProjectionElem::Deref] } => {
PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => {
err.span_label(span, format!("cannot {ACT}", ACT = act));
match opt_source {

View file

@ -5,7 +5,7 @@ use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
use rustc::lint::builtin::UNUSED_MUT;
use rustc::mir::{
read_only, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability, Operand, Place,
PlaceBase, PlaceElem, PlaceRef, ReadOnlyBodyAndCache,
PlaceElem, PlaceRef, ReadOnlyBodyAndCache,
};
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
@ -815,7 +815,7 @@ enum InitializationRequiringAction {
}
struct RootPlace<'d, 'tcx> {
place_base: &'d PlaceBase,
place_local: &'d Local,
place_projection: &'d [PlaceElem<'tcx>],
is_local_mutation_allowed: LocalMutationIsAllowed,
}
@ -1252,11 +1252,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
this.used_mut_upvars.push(field);
}
} else {
match place.base {
PlaceBase::Local(local) => {
this.used_mut.insert(local);
}
}
this.used_mut.insert(place.local);
}
};
@ -1380,7 +1376,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("check_for_invalidation_at_exit({:?})", borrow);
let place = &borrow.borrowed_place;
let deref = [ProjectionElem::Deref];
let mut root_place = PlaceRef { base: &place.base, projection: &[] };
let mut root_place = PlaceRef { local: &place.local, projection: &[] };
// FIXME(nll-rfc#40): do more precise destructor tracking here. For now
// we just know that all locals are dropped at function exit (otherwise
@ -1388,19 +1384,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
//
// FIXME: allow thread-locals to borrow other thread locals?
let (might_be_alive, will_be_dropped) = match root_place.base {
PlaceBase::Local(local) => {
if self.body.local_decls[*local].is_ref_to_thread_local() {
// Thread-locals might be dropped after the function exits
// We have to dereference the outer reference because
// borrows don't conflict behind shared references.
root_place.projection = &deref;
(true, true)
} else {
(false, self.locals_are_invalidated_at_exit)
}
}
};
let (might_be_alive, will_be_dropped) =
if self.body.local_decls[*root_place.local].is_ref_to_thread_local() {
// Thread-locals might be dropped after the function exits
// We have to dereference the outer reference because
// borrows don't conflict behind shared references.
root_place.projection = &deref;
(true, true)
} else {
(false, self.locals_are_invalidated_at_exit)
};
if !will_be_dropped {
debug!("place_is_invalidated_at_exit({:?}) - won't be dropped", place);
@ -1738,9 +1731,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place_span.0.projection
{
let place_ty =
Place::ty_from(place_span.0.base, base_proj, self.body(), self.infcx.tcx);
Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx);
if let ty::Array(..) = place_ty.ty.kind {
let array_place = PlaceRef { base: place_span.0.base, projection: base_proj };
let array_place = PlaceRef { local: place_span.0.local, projection: base_proj };
self.check_if_subslice_element_is_moved(
location,
desired_action,
@ -1837,7 +1830,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.check_if_full_path_is_moved(
location, InitializationRequiringAction::Use,
(PlaceRef {
base: &place.base,
local: &place.local,
projection: proj_base,
}, span), flow_state);
// (base initialized; no need to
@ -1855,13 +1848,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// assigning to `P.f` requires `P` itself
// be already initialized
let tcx = self.infcx.tcx;
let base_ty = Place::ty_from(&place.base, proj_base, self.body(), tcx).ty;
let base_ty = Place::ty_from(&place.local, proj_base, self.body(), tcx).ty;
match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved(
location, InitializationRequiringAction::Assignment,
(PlaceRef {
base: &place.base,
local: &place.local,
projection: proj_base,
}, span), flow_state);
@ -1874,23 +1867,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// is allowed, remove this match arm.
ty::Adt(..) | ty::Tuple(..) => {
check_parent_of_field(self, location, PlaceRef {
base: &place.base,
local: &place.local,
projection: proj_base,
}, span, flow_state);
match place.base {
// rust-lang/rust#21232,
// #54499, #54986: during
// period where we reject
// partial initialization, do
// not complain about
// unnecessary `mut` on an
// attempt to do a partial
// initialization.
PlaceBase::Local(local) => {
self.used_mut.insert(local);
}
}
// rust-lang/rust#21232, #54499, #54986: during period where we reject
// partial initialization, do not complain about unnecessary `mut` on
// an attempt to do a partial initialization.
self.used_mut.insert(place.local);
}
_ => {}
@ -1968,7 +1952,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// of the union - we should error in that case.
let tcx = this.infcx.tcx;
if let ty::Adt(def, _) =
Place::ty_from(base.base, base.projection, this.body(), tcx).ty.kind
Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind
{
if def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| {
@ -2087,9 +2071,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// partial initialization, do not complain about mutability
// errors except for actual mutation (as opposed to an attempt
// to do a partial initialization).
let previously_initialized = match place.base {
PlaceBase::Local(local) => self.is_local_ever_initialized(local, flow_state).is_some(),
};
let previously_initialized =
self.is_local_ever_initialized(place.local, flow_state).is_some();
// at this point, we have set up the error reporting state.
if previously_initialized {
@ -2118,11 +2101,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Adds the place into the used mutable variables set
fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) {
match root_place {
RootPlace {
place_base: PlaceBase::Local(local),
place_projection: [],
is_local_mutation_allowed,
} => {
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
// If the local may have been initialized, and it is now currently being
// mutated, then it is justified to be annotated with the `mut`
// keyword, since the mutation may be a possible reassignment.
@ -2133,18 +2112,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
RootPlace {
place_base: _,
place_local: _,
place_projection: _,
is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
} => {}
RootPlace {
place_base,
place_local,
place_projection: place_projection @ [.., _],
is_local_mutation_allowed: _,
} => {
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
base: &place_base,
projection: &place_projection,
local: place_local,
projection: place_projection,
}) {
self.used_mut_upvars.push(field);
}
@ -2160,34 +2139,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
is_local_mutation_allowed: LocalMutationIsAllowed,
) -> Result<RootPlace<'d, 'tcx>, PlaceRef<'d, 'tcx>> {
match place {
PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
PlaceRef { local, projection: [] } => {
let local = &self.body.local_decls[*local];
match local.mutability {
Mutability::Not => match is_local_mutation_allowed {
LocalMutationIsAllowed::Yes => Ok(RootPlace {
place_base: place.base,
place_local: place.local,
place_projection: place.projection,
is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
}),
LocalMutationIsAllowed::ExceptUpvars => Ok(RootPlace {
place_base: place.base,
place_local: place.local,
place_projection: place.projection,
is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars,
}),
LocalMutationIsAllowed::No => Err(place),
},
Mutability::Mut => Ok(RootPlace {
place_base: place.base,
place_local: place.local,
place_projection: place.projection,
is_local_mutation_allowed,
}),
}
}
PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
match elem {
ProjectionElem::Deref => {
let base_ty =
Place::ty_from(place.base, proj_base, self.body(), self.infcx.tcx).ty;
Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty;
// Check the kind of deref to decide
match base_ty.kind {
@ -2206,7 +2185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
};
self.is_mutable(
PlaceRef { base: place.base, projection: proj_base },
PlaceRef { local: place.local, projection: proj_base },
mode,
)
}
@ -2219,7 +2198,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// `*mut` raw pointers are always mutable, regardless of
// context. The users have to check by themselves.
hir::Mutability::Mut => Ok(RootPlace {
place_base: place.base,
place_local: place.local,
place_projection: place.projection,
is_local_mutation_allowed,
}),
@ -2227,7 +2206,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
// `Box<T>` owns its content, so mutable if its location is mutable
_ if base_ty.is_box() => self.is_mutable(
PlaceRef { base: place.base, projection: proj_base },
PlaceRef { local: place.local, projection: proj_base },
is_local_mutation_allowed,
),
// Deref should only be for reference, pointers or boxes
@ -2283,11 +2262,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// }
// ```
let _ = self.is_mutable(
PlaceRef { base: place.base, projection: proj_base },
PlaceRef { local: place.local, projection: proj_base },
is_local_mutation_allowed,
)?;
Ok(RootPlace {
place_base: place.base,
place_local: place.local,
place_projection: place.projection,
is_local_mutation_allowed,
})
@ -2295,7 +2274,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
} else {
self.is_mutable(
PlaceRef { base: place.base, projection: proj_base },
PlaceRef { local: place.local, projection: proj_base },
is_local_mutation_allowed,
)
}
@ -2321,7 +2300,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
match place_projection {
[base @ .., ProjectionElem::Field(field, _ty)] => {
let tcx = self.infcx.tcx;
let base_ty = Place::ty_from(place_ref.base, base, self.body(), tcx).ty;
let base_ty = Place::ty_from(place_ref.local, base, self.body(), tcx).ty;
if (base_ty.is_closure() || base_ty.is_generator())
&& (!by_ref || self.upvars[field.index()].by_ref)

View file

@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict;
use crate::borrow_check::AccessDepth;
use crate::dataflow::indexes::BorrowIndex;
use rustc::mir::BorrowKind;
use rustc::mir::{BasicBlock, Body, Location, Place, PlaceBase};
use rustc::mir::{BasicBlock, Body, Location, Place};
use rustc::ty::TyCtxt;
use rustc_data_structures::graph::dominators::Dominators;
@ -131,9 +131,7 @@ pub(super) fn is_active<'tcx>(
/// Determines if a given borrow is borrowing local data
/// This is called for all Yield expressions on movable generators
pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
match place.base {
// Reborrow of already borrowed data is ignored
// Any errors will be caught on the initial borrow
PlaceBase::Local(_) => !place.is_indirect(),
}
// Reborrow of already borrowed data is ignored
// Any errors will be caught on the initial borrow
!place.is_indirect()
}

View file

@ -1,6 +1,6 @@
use crate::borrow_check::borrow_set::LocalsStateAtExit;
use rustc::mir::ProjectionElem;
use rustc::mir::{Body, Mutability, Place, PlaceBase};
use rustc::mir::{Body, Mutability, Place};
use rustc::ty::{self, TyCtxt};
use rustc_hir as hir;
@ -25,40 +25,35 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
body: &Body<'tcx>,
locals_state_at_exit: &LocalsStateAtExit,
) -> bool {
let local = match self.base {
// If a local variable is immutable, then we only need to track borrows to guard
// against two kinds of errors:
// * The variable being dropped while still borrowed (e.g., because the fn returns
// a reference to a local variable)
// * The variable being moved while still borrowed
//
// In particular, the variable cannot be mutated -- the "access checks" will fail --
// so we don't have to worry about mutation while borrowed.
PlaceBase::Local(local) => match locals_state_at_exit {
LocalsStateAtExit::AllAreInvalidated => local,
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
let ignore = !has_storage_dead_or_moved.contains(local)
&& body.local_decls[local].mutability == Mutability::Not;
debug!("ignore_borrow: local {:?} => {:?}", local, ignore);
if ignore {
return true;
} else {
local
}
}
},
};
// If a local variable is immutable, then we only need to track borrows to guard
// against two kinds of errors:
// * The variable being dropped while still borrowed (e.g., because the fn returns
// a reference to a local variable)
// * The variable being moved while still borrowed
//
// In particular, the variable cannot be mutated -- the "access checks" will fail --
// so we don't have to worry about mutation while borrowed.
if let LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } =
locals_state_at_exit
{
let ignore = !has_storage_dead_or_moved.contains(self.local)
&& body.local_decls[self.local].mutability == Mutability::Not;
debug!("ignore_borrow: local {:?} => {:?}", self.local, ignore);
if ignore {
return true;
}
}
for (i, elem) in self.projection.iter().enumerate() {
let proj_base = &self.projection[..i];
if *elem == ProjectionElem::Deref {
let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty;
let ty = Place::ty_from(&self.local, proj_base, body, tcx).ty;
match ty.kind {
ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
// For references to thread-local statics, we do need
// to track the borrow.
if body.local_decls[local].is_ref_to_thread_local() {
if body.local_decls[self.local].is_ref_to_thread_local() {
continue;
}
return true;

View file

@ -1,7 +1,7 @@
use crate::borrow_check::ArtificialField;
use crate::borrow_check::Overlap;
use crate::borrow_check::{AccessDepth, Deep, Shallow};
use rustc::mir::{Body, BorrowKind, Place, PlaceBase, PlaceElem, PlaceRef, ProjectionElem};
use rustc::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
use rustc::ty::{self, TyCtxt};
use rustc_hir as hir;
use std::cmp::max;
@ -119,10 +119,10 @@ fn place_components_conflict<'tcx>(
// and either equal or disjoint.
// - If we did run out of access, the borrow can access a part of it.
let borrow_base = &borrow_place.base;
let access_base = access_place.base;
let borrow_local = &borrow_place.local;
let access_local = access_place.local;
match place_base_conflict(borrow_base, access_base) {
match place_base_conflict(borrow_local, access_local) {
Overlap::Arbitrary => {
bug!("Two base can't return Arbitrary");
}
@ -161,7 +161,7 @@ fn place_components_conflict<'tcx>(
match place_projection_conflict(
tcx,
body,
borrow_base,
borrow_local,
borrow_proj_base,
borrow_c,
access_c,
@ -208,7 +208,7 @@ fn place_components_conflict<'tcx>(
// access cares about.
let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
let base_ty = Place::ty_from(borrow_base, proj_base, body, tcx).ty;
let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
match (elem, &base_ty.kind, access) {
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
@ -293,19 +293,15 @@ fn place_components_conflict<'tcx>(
// Given that the bases of `elem1` and `elem2` are always either equal
// or disjoint (and have the same type!), return the overlap situation
// between `elem1` and `elem2`.
fn place_base_conflict(elem1: &PlaceBase, elem2: &PlaceBase) -> Overlap {
match (elem1, elem2) {
(PlaceBase::Local(l1), PlaceBase::Local(l2)) => {
if l1 == l2 {
// the same local - base case, equal
debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
Overlap::EqualOrDisjoint
} else {
// different locals - base case, disjoint
debug!("place_element_conflict: DISJOINT-LOCAL");
Overlap::Disjoint
}
}
fn place_base_conflict(l1: &Local, l2: &Local) -> Overlap {
if l1 == l2 {
// the same local - base case, equal
debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
Overlap::EqualOrDisjoint
} else {
// different locals - base case, disjoint
debug!("place_element_conflict: DISJOINT-LOCAL");
Overlap::Disjoint
}
}
@ -315,7 +311,7 @@ fn place_base_conflict(elem1: &PlaceBase, elem2: &PlaceBase) -> Overlap {
fn place_projection_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
pi1_base: &PlaceBase,
pi1_local: &Local,
pi1_proj_base: &[PlaceElem<'tcx>],
pi1_elem: &PlaceElem<'tcx>,
pi2_elem: &PlaceElem<'tcx>,
@ -333,7 +329,7 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
Overlap::EqualOrDisjoint
} else {
let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty;
let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
match ty.kind {
ty::Adt(def, _) if def.is_union() => {
// Different fields of a union, we are basically stuck.

View file

@ -9,7 +9,7 @@
use super::MirBorrowckCtxt;
use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
use rustc::mir::{Place, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
use rustc::ty::{self, TyCtxt};
use rustc_hir as hir;
@ -19,7 +19,7 @@ pub trait IsPrefixOf<'cx, 'tcx> {
impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
self.base == other.base
self.local == other.local
&& self.projection.len() <= other.projection.len()
&& self.projection == &other.projection[..self.projection.len()]
}
@ -69,22 +69,23 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
'cursor: loop {
match &cursor {
PlaceRef { base: PlaceBase::Local(_), projection: [] } => {
PlaceRef { local: _, projection: [] } => {
self.next = None;
return Some(cursor);
}
PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
match elem {
ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
// FIXME: add union handling
self.next = Some(PlaceRef { base: cursor.base, projection: proj_base });
self.next =
Some(PlaceRef { local: cursor.local, projection: proj_base });
return Some(cursor);
}
ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. }
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Index(_) => {
cursor = PlaceRef { base: cursor.base, projection: proj_base };
cursor = PlaceRef { local: cursor.local, projection: proj_base };
continue 'cursor;
}
ProjectionElem::Deref => {
@ -105,7 +106,8 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
PrefixSet::All => {
// All prefixes: just blindly enqueue the base
// of the projection.
self.next = Some(PlaceRef { base: cursor.base, projection: proj_base });
self.next =
Some(PlaceRef { local: cursor.local, projection: proj_base });
return Some(cursor);
}
PrefixSet::Supporting => {
@ -118,7 +120,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
// derefs, except we stop at the deref of a shared
// reference.
let ty = Place::ty_from(cursor.base, proj_base, *self.body, self.tcx).ty;
let ty = Place::ty_from(cursor.local, proj_base, *self.body, self.tcx).ty;
match ty.kind {
ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
// don't continue traversing over derefs of raw pointers or shared
@ -128,12 +130,14 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
}
ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => {
self.next = Some(PlaceRef { base: cursor.base, projection: proj_base });
self.next =
Some(PlaceRef { local: cursor.local, projection: proj_base });
return Some(cursor);
}
ty::Adt(..) if ty.is_box() => {
self.next = Some(PlaceRef { base: cursor.base, projection: proj_base });
self.next =
Some(PlaceRef { local: cursor.local, projection: proj_base });
return Some(cursor);
}

View file

@ -465,9 +465,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
) -> PlaceTy<'tcx> {
debug!("sanitize_place: {:?}", place);
let mut place_ty = match &place.base {
PlaceBase::Local(index) => PlaceTy::from_ty(self.body.local_decls[*index].ty),
};
let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
if place.projection.is_empty() {
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
@ -2389,7 +2387,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
match elem {
ProjectionElem::Deref => {
let tcx = self.infcx.tcx;
let base_ty = Place::ty_from(&borrowed_place.base, proj_base, body, tcx).ty;
let base_ty = Place::ty_from(&borrowed_place.local, proj_base, body, tcx).ty;
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.kind {

View file

@ -1,5 +1,5 @@
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::{Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind};
use rustc::mir::{Local, Location, Place, Statement, StatementKind, TerminatorKind};
use rustc_data_structures::fx::FxHashSet;
@ -57,11 +57,7 @@ impl GatherUsedMutsVisitor<'_, '_, '_> {
// be those that were never initialized - we will consider those as being used as
// they will either have been removed by unreachable code optimizations; or linted
// as unused variables.
match into.base {
PlaceBase::Local(local) => {
self.never_initialized_mut_locals.remove(&local);
}
}
self.never_initialized_mut_locals.remove(&into.local);
}
}
@ -82,13 +78,11 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc
fn visit_statement(&mut self, statement: &Statement<'tcx>, _location: Location) {
match &statement.kind {
StatementKind::Assign(box (into, _)) => {
match into.base {
PlaceBase::Local(local) => debug!(
"visit_statement: statement={:?} local={:?} \
never_initialized_mut_locals={:?}",
statement, local, self.never_initialized_mut_locals
),
}
debug!(
"visit_statement: statement={:?} local={:?} \
never_initialized_mut_locals={:?}",
statement, into.local, self.never_initialized_mut_locals
);
self.remove_never_initialized_mut_locals(into);
}
_ => {}

View file

@ -20,13 +20,13 @@ use rustc_index::vec::Idx;
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
#[derive(Clone)]
struct PlaceBuilder<'tcx> {
base: PlaceBase,
local: Local,
projection: Vec<PlaceElem<'tcx>>,
}
impl PlaceBuilder<'tcx> {
fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
Place { base: self.base, projection: tcx.intern_place_elems(&self.projection) }
Place { local: self.local, projection: tcx.intern_place_elems(&self.projection) }
}
fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
@ -49,13 +49,7 @@ impl PlaceBuilder<'tcx> {
impl From<Local> for PlaceBuilder<'tcx> {
fn from(local: Local) -> Self {
Self { base: local.into(), projection: Vec::new() }
}
}
impl From<PlaceBase> for PlaceBuilder<'tcx> {
fn from(base: PlaceBase) -> Self {
Self { base, projection: Vec::new() }
Self { local, projection: Vec::new() }
}
}
@ -370,7 +364,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
) {
let tcx = self.hir.tcx();
let place_ty =
Place::ty_from(&base_place.base, &base_place.projection, &self.local_decls, tcx);
Place::ty_from(&base_place.local, &base_place.projection, &self.local_decls, tcx);
if let ty::Slice(_) = place_ty.ty.kind {
// We need to create fake borrows to ensure that the bounds
// check that we just did stays valid. Since we can't assign to
@ -380,7 +374,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
match elem {
ProjectionElem::Deref => {
let fake_borrow_deref_ty = Place::ty_from(
&base_place.base,
&base_place.local,
&base_place.projection[..idx],
&self.local_decls,
tcx,
@ -398,14 +392,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Rvalue::Ref(
tcx.lifetimes.re_erased,
BorrowKind::Shallow,
Place { base: base_place.base.clone(), projection },
Place { local: base_place.local.clone(), projection },
),
);
fake_borrow_temps.push(fake_borrow_temp);
}
ProjectionElem::Index(_) => {
let index_ty = Place::ty_from(
&base_place.base,
&base_place.local,
&base_place.projection[..idx],
&self.local_decls,
tcx,

View file

@ -393,26 +393,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let arg_place = unpack!(block = this.as_place(block, arg));
let mutability = match arg_place.as_ref() {
PlaceRef { base: &PlaceBase::Local(local), projection: &[] } => {
this.local_decls[local].mutability
}
PlaceRef { base: &PlaceBase::Local(local), projection: &[ProjectionElem::Deref] } => {
PlaceRef { local, projection: &[] } => this.local_decls[*local].mutability,
PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
debug_assert!(
this.local_decls[local].is_ref_for_guard(),
this.local_decls[*local].is_ref_for_guard(),
"Unexpected capture place",
);
this.local_decls[local].mutability
this.local_decls[*local].mutability
}
PlaceRef {
ref base,
ref local,
projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
}
| PlaceRef {
ref base,
ref local,
projection:
&[ref proj_base @ .., ProjectionElem::Field(upvar_index, _), ProjectionElem::Deref],
} => {
let place = PlaceRef { base, projection: proj_base };
let place = PlaceRef { local, projection: proj_base };
// Not projected from the implicit `self` in a closure.
debug_assert!(

View file

@ -890,7 +890,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let proj_base = &source.projection[..i];
fake_borrows.insert(Place {
base: source.base.clone(),
local: source.local.clone(),
projection: self.hir.tcx().intern_place_elems(proj_base),
});
}
@ -1241,7 +1241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Insert a shallow borrow after a deref. For other
// projections the borrow of prefix_cursor will
// conflict with any mutation of base.
all_fake_borrows.push(PlaceRef { base: &place.base, projection: proj_base });
all_fake_borrows.push(PlaceRef { local: &place.local, projection: proj_base });
}
}
@ -1258,7 +1258,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.into_iter()
.map(|matched_place_ref| {
let matched_place = Place {
base: matched_place_ref.base.clone(),
local: matched_place_ref.local.clone(),
projection: tcx.intern_place_elems(matched_place_ref.projection),
};
let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;

View file

@ -834,7 +834,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
span: tcx_hir.span(var_id),
},
place: Place {
base: closure_env_arg.into(),
local: closure_env_arg.into(),
projection: tcx.intern_place_elems(&projs),
},
});

View file

@ -86,10 +86,7 @@ struct BorrowedLocalsVisitor<'gk> {
}
fn find_local(place: &Place<'_>) -> Option<Local> {
match place.base {
PlaceBase::Local(local) if !place.is_indirect() => Some(local),
_ => None,
}
if !place.is_indirect() { Some(place.local) } else { None }
}
impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> {

View file

@ -1,4 +1,4 @@
use rustc::mir::{self, Body, Location, Place, PlaceBase};
use rustc::mir::{self, Body, Location, Place};
use rustc::ty::RegionVid;
use rustc::ty::TyCtxt;
@ -195,38 +195,34 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
fn kill_borrows_on_place(&self, trans: &mut GenKillSet<BorrowIndex>, place: &Place<'tcx>) {
debug!("kill_borrows_on_place: place={:?}", place);
match place.base {
PlaceBase::Local(local) => {
let other_borrows_of_local =
self.borrow_set.local_map.get(&local).into_iter().flat_map(|bs| bs.into_iter());
let other_borrows_of_local =
self.borrow_set.local_map.get(&place.local).into_iter().flat_map(|bs| bs.into_iter());
// If the borrowed place is a local with no projections, all other borrows of this
// local must conflict. This is purely an optimization so we don't have to call
// `places_conflict` for every borrow.
if place.projection.is_empty() {
if !self.body.local_decls[local].is_ref_to_static() {
trans.kill_all(other_borrows_of_local);
}
return;
}
// By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
// pair of array indices are unequal, so that when `places_conflict` returns true, we
// will be assured that two places being compared definitely denotes the same sets of
// locations.
let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
places_conflict(
self.tcx,
self.body,
&self.borrow_set.borrows[i].borrowed_place,
place,
PlaceConflictBias::NoOverlap,
)
});
trans.kill_all(definitely_conflicting_borrows);
// If the borrowed place is a local with no projections, all other borrows of this
// local must conflict. This is purely an optimization so we don't have to call
// `places_conflict` for every borrow.
if place.projection.is_empty() {
if !self.body.local_decls[place.local].is_ref_to_static() {
trans.kill_all(other_borrows_of_local);
}
return;
}
// By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
// pair of array indices are unequal, so that when `places_conflict` returns true, we
// will be assured that two places being compared definitely denotes the same sets of
// locations.
let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
places_conflict(
self.tcx,
self.body,
&self.borrow_set.borrows[i].borrowed_place,
place,
PlaceConflictBias::NoOverlap,
)
});
trans.kill_all(definitely_conflicting_borrows);
}
}

View file

@ -111,12 +111,8 @@ impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
if self.borrow_allows_mutation(kind, borrowed_place) {
match borrowed_place.base {
mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect() => {
self.trans.gen(borrowed_local)
}
_ => (),
if !borrowed_place.is_indirect() {
self.trans.gen(borrowed_place.local);
}
}
}

View file

@ -115,14 +115,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
match stmt.kind {
StatementKind::StorageDead(l) => sets.kill(l),
StatementKind::Assign(box (ref place, _))
| StatementKind::SetDiscriminant { box ref place, .. } => match place.base {
PlaceBase::Local(local) => sets.gen(local),
},
| StatementKind::SetDiscriminant { box ref place, .. } => {
sets.gen(place.local);
}
StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
for p in &**outputs {
match p.base {
PlaceBase::Local(local) => sets.gen(local),
}
for place in &**outputs {
sets.gen(place.local);
}
}
_ => (),
@ -138,10 +136,8 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
self.check_for_borrow(sets, loc);
if let TerminatorKind::Call {
destination: Some((Place { base: PlaceBase::Local(local), .. }, _)),
..
} = self.body[loc.block].terminator().kind
if let TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } =
self.body[loc.block].terminator().kind
{
sets.gen(local);
}
@ -169,11 +165,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
_dest_bb: mir::BasicBlock,
dest_place: &mir::Place<'tcx>,
) {
match dest_place.base {
PlaceBase::Local(local) => {
in_out.insert(local);
}
}
in_out.insert(dest_place.local);
}
}

View file

@ -96,9 +96,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
/// Maybe we should have separate "borrowck" and "moveck" modes.
fn move_path_for(&mut self, place: &Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
debug!("lookup({:?})", place);
let mut base = match place.base {
PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[local],
};
let mut base = self.builder.data.rev_lookup.locals[place.local];
// The move path index of the first union that we find. Once this is
// some we stop creating child move paths, since moves from unions
@ -111,7 +109,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
let proj_base = &place.projection[..i];
let body = self.builder.body;
let tcx = self.builder.tcx;
let place_ty = Place::ty_from(&place.base, proj_base, body, tcx).ty;
let place_ty = Place::ty_from(&place.local, proj_base, body, tcx).ty;
match place_ty.kind {
ty::Ref(..) | ty::RawPtr(..) => {
let proj = &place.projection[..i + 1];
@ -119,7 +117,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
self.loc,
BorrowedContent {
target_place: Place {
base: place.base.clone(),
local: place.local,
projection: tcx.intern_place_elems(proj),
},
},
@ -160,7 +158,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
if union_path.is_none() {
base = self.add_move_path(base, elem, |tcx| Place {
base: place.base.clone(),
local: place.local.clone(),
projection: tcx.intern_place_elems(&place.projection[..i + 1]),
});
}
@ -433,7 +431,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// `ConstIndex` patterns. This is done to ensure that all move paths
// are disjoint, which is expected by drop elaboration.
let base_place = Place {
base: place.base.clone(),
local: place.local.clone(),
projection: self.builder.tcx.intern_place_elems(base),
};
let base_path = match self.move_path_for(&base_place) {
@ -494,10 +492,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// of the union so it is marked as initialized again.
if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection {
if let ty::Adt(def, _) =
Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.kind
Place::ty_from(place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind
{
if def.is_union() {
place = PlaceRef { base: place.base, projection: proj_base }
place = PlaceRef { local: place.local, projection: proj_base }
}
}
}

View file

@ -246,9 +246,7 @@ impl MovePathLookup {
// unknown place, but will rather return the nearest available
// parent.
pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult {
let mut result = match place.base {
PlaceBase::Local(local) => self.locals[*local],
};
let mut result = self.locals[*place.local];
for elem in place.projection.iter() {
if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {

View file

@ -462,17 +462,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
place: &mir::Place<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
use rustc::mir::PlaceBase;
let base_op = match &place.base {
PlaceBase::Local(mir::RETURN_PLACE) => throw_unsup!(ReadFromReturnPointer),
PlaceBase::Local(local) => {
let base_op = match place.local {
mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer),
local => {
// Do not use the layout passed in as argument if the base we are looking at
// here is not the entire place.
// FIXME use place_projection.is_empty() when is available
let layout = if place.projection.is_empty() { layout } else { None };
self.access_local(self.frame(), *local, layout)?
self.access_local(self.frame(), local, layout)?
}
};

View file

@ -624,10 +624,8 @@ where
&mut self,
place: &mir::Place<'tcx>,
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::PlaceBase;
let mut place_ty = match &place.base {
PlaceBase::Local(mir::RETURN_PLACE) => {
let mut place_ty = match place.local {
mir::RETURN_PLACE => {
// `return_place` has the *caller* layout, but we want to use our
// `layout to verify our assumption. The caller will validate
// their layout on return.
@ -648,10 +646,10 @@ where
))?,
}
}
PlaceBase::Local(local) => PlaceTy {
local => PlaceTy {
// This works even for dead/uninitialized locals; we check further when writing
place: Place::Local { frame: self.cur_frame(), local: *local },
layout: self.layout_of_local(self.frame(), *local, None)?,
place: Place::Local { frame: self.cur_frame(), local: local },
layout: self.layout_of_local(self.frame(), local, None)?,
},
};

View file

@ -182,7 +182,7 @@ use rustc::mir::interpret::{AllocId, ConstValue};
use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
use rustc::mir::mono::{InstantiationMode, MonoItem};
use rustc::mir::visit::Visitor as MirVisitor;
use rustc::mir::{self, Location, PlaceBase};
use rustc::mir::{self, Local, Location};
use rustc::session::config::EntryFnType;
use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
use rustc::ty::print::obsolete::DefPathBasedNames;
@ -642,15 +642,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
fn visit_place_base(
&mut self,
place_base: &mir::PlaceBase,
_place_local: &Local,
_context: mir::visit::PlaceContext,
_location: Location,
) {
match place_base {
PlaceBase::Local(_) => {
// Locals have no relevance for collector.
}
}
}
}

View file

@ -38,12 +38,15 @@ pub trait Qualif {
place: PlaceRef<'_, 'tcx>,
) -> bool {
if let [proj_base @ .., elem] = place.projection {
let base_qualif =
Self::in_place(cx, per_local, PlaceRef { base: place.base, projection: proj_base });
let base_qualif = Self::in_place(
cx,
per_local,
PlaceRef { local: place.local, projection: proj_base },
);
let qualif = base_qualif
&& Self::in_any_value_of_ty(
cx,
Place::ty_from(place.base, proj_base, *cx.body, cx.tcx)
Place::ty_from(place.local, proj_base, *cx.body, cx.tcx)
.projection_ty(cx.tcx, elem)
.ty,
);
@ -75,8 +78,8 @@ pub trait Qualif {
place: PlaceRef<'_, 'tcx>,
) -> bool {
match place {
PlaceRef { base: PlaceBase::Local(local), projection: [] } => per_local(*local),
PlaceRef { base: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
PlaceRef { local, projection: [] } => per_local(*local),
PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
}
}
@ -146,12 +149,12 @@ pub trait Qualif {
Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
// Special-case reborrows to be more like a copy of the reference.
if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
let base_ty = Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx).ty;
if let ty::Ref(..) = base_ty.kind {
return Self::in_place(
cx,
per_local,
PlaceRef { base: &place.base, projection: proj_base },
PlaceRef { local: &place.local, projection: proj_base },
);
}
}

View file

@ -47,15 +47,15 @@ where
debug_assert!(!place.is_indirect());
match (value, place.as_ref()) {
(true, mir::PlaceRef { base: &mir::PlaceBase::Local(local), .. }) => {
self.qualifs_per_local.insert(local);
(true, mir::PlaceRef { local, .. }) => {
self.qualifs_per_local.insert(*local);
}
// For now, we do not clear the qualif if a local is overwritten in full by
// an unqualified rvalue (e.g. `y = 5`). This is to be consistent
// with aggregates where we overwrite all fields with assignments, which would not
// get this feature.
(false, mir::PlaceRef { base: &mir::PlaceBase::Local(_local), projection: &[] }) => {
(false, mir::PlaceRef { local: _, projection: &[] }) => {
// self.qualifs_per_local.remove(*local);
}

View file

@ -304,8 +304,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
}
};
self.visit_place_base(&place.base, ctx, location);
self.visit_projection(&place.base, reborrowed_proj, ctx, location);
self.visit_place_base(&place.local, ctx, location);
self.visit_projection(&place.local, reborrowed_proj, ctx, location);
return;
}
}
@ -317,8 +317,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
}
Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
};
self.visit_place_base(&place.base, ctx, location);
self.visit_projection(&place.base, reborrowed_proj, ctx, location);
self.visit_place_base(&place.local, ctx, location);
self.visit_projection(&place.local, reborrowed_proj, ctx, location);
return;
}
}
@ -412,23 +412,14 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
}
}
fn visit_place_base(
&mut self,
place_base: &PlaceBase,
context: PlaceContext,
location: Location,
) {
fn visit_place_base(&mut self, place_local: &Local, context: PlaceContext, location: Location) {
trace!(
"visit_place_base: place_base={:?} context={:?} location={:?}",
place_base,
"visit_place_base: place_local={:?} context={:?} location={:?}",
place_local,
context,
location,
);
self.super_place_base(place_base, context, location);
match place_base {
PlaceBase::Local(_) => {}
}
self.super_place_base(place_local, context, location);
}
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
@ -441,30 +432,30 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
}
fn visit_projection_elem(
&mut self,
place_base: &PlaceBase,
place_local: &Local,
proj_base: &[PlaceElem<'tcx>],
elem: &PlaceElem<'tcx>,
context: PlaceContext,
location: Location,
) {
trace!(
"visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
"visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
context={:?} location={:?}",
place_base,
place_local,
proj_base,
elem,
context,
location,
);
self.super_projection_elem(place_base, proj_base, elem, context, location);
self.super_projection_elem(place_local, proj_base, elem, context, location);
match elem {
ProjectionElem::Deref => {
let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
if let ty::RawPtr(_) = base_ty.kind {
if proj_base.is_empty() {
if let (PlaceBase::Local(local), []) = (place_base, proj_base) {
if let (local, []) = (place_local, proj_base) {
let decl = &self.body.local_decls[*local];
if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
let span = decl.source_info.span;
@ -485,7 +476,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
| ProjectionElem::Subslice { .. }
| ProjectionElem::Field(..)
| ProjectionElem::Index(_) => {
let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
match base_ty.ty_adt_def() {
Some(def) if def.is_union() => {
self.check_op(ops::UnionAccess);
@ -669,19 +660,15 @@ fn place_as_reborrow(
// A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
// that points to the allocation for the static. Don't treat these as reborrows.
match place.base {
PlaceBase::Local(local) => {
if body.local_decls[local].is_ref_to_static() {
return None;
}
}
if body.local_decls[place.local].is_ref_to_static() {
return None;
}
// Ensure the type being derefed is a reference and not a raw pointer.
//
// This is sufficient to prevent an access to a `static mut` from being marked as a
// reborrow, even if the check above were to disappear.
let inner_ty = Place::ty_from(&place.base, inner, body, tcx).ty;
let inner_ty = Place::ty_from(&place.local, inner, body, tcx).ty;
match inner_ty.kind {
ty::Ref(..) => Some(inner),
_ => None,

View file

@ -190,12 +190,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
match place.base {
PlaceBase::Local(..) => {
// Locals are safe.
}
}
for (i, elem) in place.projection.iter().enumerate() {
let proj_base = &place.projection[..i];
@ -223,7 +217,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
}
let is_borrow_of_interior_mut = context.is_borrow()
&& !Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty.is_freeze(
&& !Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty.is_freeze(
self.tcx,
self.param_env,
self.source_info.span,
@ -238,7 +232,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use());
}
let old_source_info = self.source_info;
if let (PlaceBase::Local(local), []) = (&place.base, proj_base) {
if let (local, []) = (&place.local, proj_base) {
let decl = &self.body.local_decls[*local];
if decl.internal {
// Internal locals are used in the `move_val_init` desugaring.
@ -266,7 +260,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
}
}
let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
let base_ty = Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty;
match base_ty.kind {
ty::RawPtr(..) => self.require_unsafe(
"dereference of raw pointer",
@ -420,7 +414,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
match elem {
ProjectionElem::Field(..) => {
let ty =
Place::ty_from(&place.base, proj_base, &self.body.local_decls, self.tcx).ty;
Place::ty_from(&place.local, proj_base, &self.body.local_decls, self.tcx)
.ty;
match ty.kind {
ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
(Bound::Unbounded, Bound::Unbounded) => {}

View file

@ -10,7 +10,7 @@ use rustc::mir::visit::{
};
use rustc::mir::{
read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant,
Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, ReadOnlyBodyAndCache, Rvalue,
Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue,
SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
UnOp, RETURN_PLACE,
};
@ -872,9 +872,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
// doesn't use the invalid value
match cond {
Operand::Move(ref place) | Operand::Copy(ref place) => {
match place.base {
PlaceBase::Local(local) => self.remove_const(local),
}
self.remove_const(place.local);
}
Operand::Constant(_) => {}
}

View file

@ -112,17 +112,17 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
}
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
if place.base == PlaceBase::Local(self_arg()) {
if place.local == self_arg() {
replace_base(
place,
Place {
base: PlaceBase::Local(self_arg()),
local: self_arg(),
projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
},
self.tcx,
);
} else {
self.visit_place_base(&mut place.base, context, location);
self.visit_place_base(&mut place.local, context, location);
for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
@ -148,11 +148,11 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
}
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
if place.base == PlaceBase::Local(self_arg()) {
if place.local == self_arg() {
replace_base(
place,
Place {
base: PlaceBase::Local(self_arg()),
local: self_arg(),
projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Field(
Field::new(0),
self.ref_gen_ty,
@ -161,7 +161,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
self.tcx,
);
} else {
self.visit_place_base(&mut place.base, context, location);
self.visit_place_base(&mut place.local, context, location);
for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
@ -173,7 +173,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
}
fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
place.base = new_base.base;
place.local = new_base.local;
let mut new_projection = new_base.projection.to_vec();
new_projection.append(&mut place.projection.to_vec());
@ -236,7 +236,7 @@ impl TransformVisitor<'tcx> {
let mut projection = base.projection.to_vec();
projection.push(ProjectionElem::Field(Field::new(idx), ty));
Place { base: base.base, projection: self.tcx.intern_place_elems(&projection) }
Place { local: base.local, projection: self.tcx.intern_place_elems(&projection) }
}
// Create a statement which changes the discriminant
@ -281,14 +281,9 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
_context: PlaceContext,
_location: Location,
) {
match place.base {
PlaceBase::Local(l) =>
// Replace an Local in the remap with a generator struct access
{
if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) {
replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
}
}
// Replace an Local in the remap with a generator struct access
if let Some(&(ty, variant_index, idx)) = self.remap.get(&place.local) {
replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
}
}

View file

@ -430,9 +430,7 @@ impl Inliner<'tcx> {
}
}
match place.base {
_ => false,
}
false
}
let dest = if dest_needs_borrow(&destination.0) {
@ -644,9 +642,7 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
fn make_integrate_local(&self, local: &Local) -> Local {
if *local == RETURN_PLACE {
match self.destination.base {
PlaceBase::Local(l) => return l,
}
return self.destination.local;
}
let idx = local.index() - 1;
@ -668,18 +664,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
}
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
match &mut place.base {
PlaceBase::Local(l) => {
// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
let dest_proj_len = self.destination.projection.len();
if *l == RETURN_PLACE && dest_proj_len > 0 {
let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
projs.extend(self.destination.projection);
projs.extend(place.projection);
// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
let dest_proj_len = self.destination.projection.len();
if place.local == RETURN_PLACE && dest_proj_len > 0 {
let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
projs.extend(self.destination.projection);
projs.extend(place.projection);
place.projection = self.tcx.intern_place_elems(&*projs);
}
}
place.projection = self.tcx.intern_place_elems(&*projs);
}
// Handles integrating any locals that occur in the base
// or projections

View file

@ -3,7 +3,7 @@
use crate::transform::{MirPass, MirSource};
use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::mir::{
read_only, Body, BodyAndCache, Constant, Local, Location, Operand, Place, PlaceBase, PlaceRef,
read_only, Body, BodyAndCache, Constant, Local, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue,
};
use rustc::ty::{self, TyCtxt};
@ -55,7 +55,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
Place {
// Replace with dummy
base: mem::replace(&mut place.base, PlaceBase::Local(Local::new(0))),
local: mem::replace(&mut place.local, Local::new(0)),
projection: self.tcx().intern_place_elems(proj_l),
}
} else {
@ -92,10 +92,10 @@ impl OptimizationFinder<'b, 'tcx> {
impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
if let Rvalue::Ref(_, _, place) = rvalue {
if let PlaceRef { base, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
place.as_ref()
{
if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
if Place::ty_from(local, proj_base, self.body, self.tcx).ty.is_region_ptr() {
self.optimizations.and_stars.insert(location);
}
}

View file

@ -308,17 +308,14 @@ impl<'tcx> Validator<'_, 'tcx> {
// We can only promote interior borrows of promotable temps (non-temps
// don't get promoted anyway).
let base = match place.base {
PlaceBase::Local(local) => local,
};
self.validate_local(base)?;
self.validate_local(place.local)?;
if place.projection.contains(&ProjectionElem::Deref) {
return Err(Unpromotable);
}
let mut has_mut_interior =
self.qualif_local::<qualifs::HasMutInterior>(base);
self.qualif_local::<qualifs::HasMutInterior>(place.local);
// HACK(eddyb) this should compute the same thing as
// `<HasMutInterior as Qualif>::in_projection` from
// `check_consts::qualifs` but without recursion.
@ -332,7 +329,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// FIXME(eddyb) this is probably excessive, with
// the exception of `union` member accesses.
let ty =
Place::ty_from(&place.base, proj_base, *self.body, self.tcx)
Place::ty_from(&place.local, proj_base, *self.body, self.tcx)
.projection_ty(self.tcx, elem)
.ty;
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@ -348,7 +345,7 @@ impl<'tcx> Validator<'_, 'tcx> {
if has_mut_interior {
return Err(Unpromotable);
}
if self.qualif_local::<qualifs::NeedsDrop>(base) {
if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
return Err(Unpromotable);
}
@ -478,10 +475,8 @@ impl<'tcx> Validator<'_, 'tcx> {
fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> {
match place {
PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
self.validate_local(*local)
}
PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
PlaceRef { local, projection: [] } => self.validate_local(*local),
PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
match *elem {
ProjectionElem::Deref | ProjectionElem::Downcast(..) => {
return Err(Unpromotable);
@ -496,7 +491,7 @@ impl<'tcx> Validator<'_, 'tcx> {
ProjectionElem::Field(..) => {
if self.const_kind.is_none() {
let base_ty =
Place::ty_from(place.base, proj_base, *self.body, self.tcx).ty;
Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty;
if let Some(def) = base_ty.ty_adt_def() {
// No promotion of union field accesses.
if def.is_union() {
@ -507,7 +502,7 @@ impl<'tcx> Validator<'_, 'tcx> {
}
}
self.validate_place(PlaceRef { base: place.base, projection: proj_base })
self.validate_place(PlaceRef { local: place.local, projection: proj_base })
}
}
}
@ -594,10 +589,12 @@ impl<'tcx> Validator<'_, 'tcx> {
// Raw reborrows can come from reference to pointer coercions,
// so are allowed.
if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty;
if let ty::Ref(..) = base_ty.kind {
return self
.validate_place(PlaceRef { base: &place.base, projection: proj_base });
return self.validate_place(PlaceRef {
local: &place.local,
projection: proj_base,
});
}
}
Err(Unpromotable)
@ -631,9 +628,9 @@ impl<'tcx> Validator<'_, 'tcx> {
// Special-case reborrows to be more like a copy of the reference.
let mut place = place.as_ref();
if let [proj_base @ .., ProjectionElem::Deref] = &place.projection {
let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty;
if let ty::Ref(..) = base_ty.kind {
place = PlaceRef { base: &place.base, projection: proj_base };
place = PlaceRef { local: &place.local, projection: proj_base };
}
}
@ -642,16 +639,15 @@ impl<'tcx> Validator<'_, 'tcx> {
// HACK(eddyb) this should compute the same thing as
// `<HasMutInterior as Qualif>::in_projection` from
// `check_consts::qualifs` but without recursion.
let mut has_mut_interior = match place.base {
PlaceBase::Local(local) => self.qualif_local::<qualifs::HasMutInterior>(*local),
};
let mut has_mut_interior =
self.qualif_local::<qualifs::HasMutInterior>(*place.local);
if has_mut_interior {
let mut place_projection = place.projection;
// FIXME(eddyb) use a forward loop instead of a reverse one.
while let [proj_base @ .., elem] = place_projection {
// FIXME(eddyb) this is probably excessive, with
// the exception of `union` member accesses.
let ty = Place::ty_from(place.base, proj_base, *self.body, self.tcx)
let ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx)
.projection_ty(self.tcx, elem)
.ty;
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@ -930,7 +926,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
)) => {
// Use the underlying local for this (necessarily interior) borrow.
let ty = place.base.ty(local_decls).ty;
let ty = local_decls.local_decls()[place.local].ty;
let span = statement.source_info.span;
let ref_ty = tcx.mk_ref(
@ -965,10 +961,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
tcx.lifetimes.re_static,
borrow_kind,
Place {
base: mem::replace(
&mut place.base,
PlaceBase::Local(promoted_ref),
),
local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(),
},
)

View file

@ -261,7 +261,7 @@ fn check_place(
ProjectionElem::Downcast(_symbol, _variant_index) => {}
ProjectionElem::Field(..) => {
let base_ty = Place::ty_from(&place.base, &proj_base, body, tcx).ty;
let base_ty = Place::ty_from(&place.local, &proj_base, body, tcx).ty;
if let Some(def) = base_ty.ty_adt_def() {
// No union field accesses in `const fn`
if def.is_union() {

View file

@ -388,9 +388,7 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
// Remove unnecessary StorageLive and StorageDead annotations.
data.statements.retain(|stmt| match &stmt.kind {
StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => self.map[*l].is_some(),
StatementKind::Assign(box (place, _)) => match place.base {
PlaceBase::Local(local) => self.map[local].is_some(),
},
StatementKind::Assign(box (place, _)) => self.map[place.local].is_some(),
_ => true,
});
self.super_basic_block_data(block, data);

View file

@ -137,9 +137,9 @@ struct VarField<'tcx> {
fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
match place.as_ref() {
PlaceRef {
base: &PlaceBase::Local(local),
local,
projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
} => Some((local, VarField { field, field_ty: ty, var_idx })),
} => Some((*local, VarField { field, field_ty: ty, var_idx })),
_ => None,
}
}

View file

@ -46,7 +46,7 @@ where
// encountered a Deref, which is ABI-aligned
ProjectionElem::Deref => break,
ProjectionElem::Field(..) => {
let ty = Place::ty_from(&place.base, proj_base, local_decls, tcx).ty;
let ty = Place::ty_from(&place.local, proj_base, local_decls, tcx).ty;
match ty.kind {
ty::Adt(def, _) if def.repr.packed() => return true,
_ => {}