Put Local, Static and Promoted as one Base variant of Place
This commit is contained in:
parent
1999a22881
commit
0f993d5a7a
63 changed files with 441 additions and 352 deletions
|
@ -209,13 +209,13 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Place<'gcx> {
|
||||||
hasher: &mut StableHasher<W>) {
|
hasher: &mut StableHasher<W>) {
|
||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
match *self {
|
match *self {
|
||||||
mir::Place::Local(ref local) => {
|
mir::Place::Base(mir::PlaceBase::Local(ref local)) => {
|
||||||
local.hash_stable(hcx, hasher);
|
local.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Place::Static(ref statik) => {
|
mir::Place::Base(mir::PlaceBase::Static(ref statik)) => {
|
||||||
statik.hash_stable(hcx, hasher);
|
statik.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Place::Promoted(ref promoted) => {
|
mir::Place::Base(mir::PlaceBase::Promoted(ref promoted)) => {
|
||||||
promoted.hash_stable(hcx, hasher);
|
promoted.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
mir::Place::Projection(ref place_projection) => {
|
mir::Place::Projection(ref place_projection) => {
|
||||||
|
|
|
@ -1896,6 +1896,14 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||||
/// changing or disturbing program state.
|
/// changing or disturbing program state.
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Place<'tcx> {
|
pub enum Place<'tcx> {
|
||||||
|
Base(PlaceBase<'tcx>),
|
||||||
|
|
||||||
|
/// projection out of a place (access a field, deref a pointer, etc)
|
||||||
|
Projection(Box<PlaceProjection<'tcx>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||||
|
pub enum PlaceBase<'tcx> {
|
||||||
/// local variable
|
/// local variable
|
||||||
Local(Local),
|
Local(Local),
|
||||||
|
|
||||||
|
@ -1904,9 +1912,6 @@ pub enum Place<'tcx> {
|
||||||
|
|
||||||
/// Constant code promoted to an injected static
|
/// Constant code promoted to an injected static
|
||||||
Promoted(Box<(Promoted, Ty<'tcx>)>),
|
Promoted(Box<(Promoted, Ty<'tcx>)>),
|
||||||
|
|
||||||
/// projection out of a place (access a field, deref a pointer, etc)
|
|
||||||
Projection(Box<PlaceProjection<'tcx>>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `DefId` of a static, along with its normalized type (which is
|
/// The `DefId` of a static, along with its normalized type (which is
|
||||||
|
@ -1994,6 +1999,8 @@ newtype_index! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Place<'tcx> {
|
impl<'tcx> Place<'tcx> {
|
||||||
|
pub const RETURN_PLACE: Place<'tcx> = Place::Base(PlaceBase::Local(RETURN_PLACE));
|
||||||
|
|
||||||
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
|
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
|
||||||
self.elem(ProjectionElem::Field(f, ty))
|
self.elem(ProjectionElem::Field(f, ty))
|
||||||
}
|
}
|
||||||
|
@ -2020,9 +2027,9 @@ impl<'tcx> Place<'tcx> {
|
||||||
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
|
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
|
||||||
pub fn local(&self) -> Option<Local> {
|
pub fn local(&self) -> Option<Local> {
|
||||||
match self {
|
match self {
|
||||||
Place::Local(local) |
|
Place::Base(PlaceBase::Local(local)) |
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base: Place::Local(local),
|
base: Place::Base(PlaceBase::Local(local)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) => Some(*local),
|
}) => Some(*local),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -2032,9 +2039,9 @@ impl<'tcx> Place<'tcx> {
|
||||||
/// Finds the innermost `Local` from this `Place`.
|
/// Finds the innermost `Local` from this `Place`.
|
||||||
pub fn base_local(&self) -> Option<Local> {
|
pub fn base_local(&self) -> Option<Local> {
|
||||||
match self {
|
match self {
|
||||||
Place::Local(local) => Some(*local),
|
Place::Base(PlaceBase::Local(local)) => Some(*local),
|
||||||
Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
|
Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
|
||||||
Place::Promoted(..) | Place::Static(..) => None,
|
Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2044,14 +2051,19 @@ impl<'tcx> Debug for Place<'tcx> {
|
||||||
use self::Place::*;
|
use self::Place::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Local(id) => write!(fmt, "{:?}", id),
|
Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
|
||||||
Static(box self::Static { def_id, ty }) => write!(
|
Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
|
||||||
fmt,
|
fmt,
|
||||||
"({}: {:?})",
|
"({}: {:?})",
|
||||||
ty::tls::with(|tcx| tcx.item_path_str(def_id)),
|
ty::tls::with(|tcx| tcx.item_path_str(def_id)),
|
||||||
ty
|
ty
|
||||||
),
|
),
|
||||||
Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1),
|
Base(PlaceBase::Promoted(ref promoted)) => write!(
|
||||||
|
fmt,
|
||||||
|
"({:?}: {:?})",
|
||||||
|
promoted.0,
|
||||||
|
promoted.1
|
||||||
|
),
|
||||||
Projection(ref data) => match data.elem {
|
Projection(ref data) => match data.elem {
|
||||||
ProjectionElem::Downcast(ref adt_def, index) => {
|
ProjectionElem::Downcast(ref adt_def, index) => {
|
||||||
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
|
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
|
||||||
|
|
|
@ -158,10 +158,10 @@ impl<'tcx> Place<'tcx> {
|
||||||
where D: HasLocalDecls<'tcx>
|
where D: HasLocalDecls<'tcx>
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
Place::Local(index) =>
|
Place::Base(PlaceBase::Local(index)) =>
|
||||||
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
|
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
|
||||||
Place::Promoted(ref data) => PlaceTy::Ty { ty: data.1 },
|
Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
|
||||||
Place::Static(ref data) =>
|
Place::Base(PlaceBase::Static(ref data)) =>
|
||||||
PlaceTy::Ty { ty: data.ty },
|
PlaceTy::Ty { ty: data.ty },
|
||||||
Place::Projection(ref proj) =>
|
Place::Projection(ref proj) =>
|
||||||
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
|
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
|
||||||
|
|
|
@ -733,13 +733,13 @@ macro_rules! make_mir_visitor {
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
match place {
|
match place {
|
||||||
Place::Local(local) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
self.visit_local(local, context, location);
|
self.visit_local(local, context, location);
|
||||||
}
|
}
|
||||||
Place::Static(static_) => {
|
Place::Base(PlaceBase::Static(static_)) => {
|
||||||
self.visit_static(static_, context, location);
|
self.visit_static(static_, context, location);
|
||||||
}
|
}
|
||||||
Place::Promoted(promoted) => {
|
Place::Base(PlaceBase::Promoted(promoted)) => {
|
||||||
self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
|
self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
|
||||||
},
|
},
|
||||||
Place::Projection(proj) => {
|
Place::Projection(proj) => {
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
||||||
location: Location) {
|
location: Location) {
|
||||||
debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
|
debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
|
||||||
|
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
||||||
self.assign(index, location);
|
self.assign(index, location);
|
||||||
if !self.fx.rvalue_creates_operand(rvalue) {
|
if !self.fx.rvalue_creates_operand(rvalue) {
|
||||||
self.not_ssa(index);
|
self.not_ssa(index);
|
||||||
|
@ -245,7 +245,8 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
|
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
|
||||||
let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx());
|
let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
|
||||||
|
self.fx.cx.tcx());
|
||||||
let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
|
let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
|
||||||
|
|
||||||
// Only need the place if we're actually dropping it.
|
// Only need the place if we're actually dropping it.
|
||||||
|
|
|
@ -249,7 +249,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
|
|
||||||
PassMode::Direct(_) | PassMode::Pair(..) => {
|
PassMode::Direct(_) | PassMode::Pair(..) => {
|
||||||
let op =
|
let op =
|
||||||
self.codegen_consume(&mut bx, &mir::Place::Local(mir::RETURN_PLACE));
|
self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE);
|
||||||
if let Ref(llval, _, align) = op.val {
|
if let Ref(llval, _, align) = op.val {
|
||||||
bx.load(llval, align)
|
bx.load(llval, align)
|
||||||
} else {
|
} else {
|
||||||
|
@ -615,8 +615,12 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
// The shuffle array argument is usually not an explicit constant,
|
// The shuffle array argument is usually not an explicit constant,
|
||||||
// but specified directly in the code. This means it gets promoted
|
// but specified directly in the code. This means it gets promoted
|
||||||
// and we can then extract the value by evaluating the promoted.
|
// and we can then extract the value by evaluating the promoted.
|
||||||
mir::Operand::Copy(mir::Place::Promoted(box(index, ty))) |
|
mir::Operand::Copy(
|
||||||
mir::Operand::Move(mir::Place::Promoted(box(index, ty))) => {
|
mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
|
||||||
|
) |
|
||||||
|
mir::Operand::Move(
|
||||||
|
mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
|
||||||
|
) => {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let cid = mir::interpret::GlobalId {
|
let cid = mir::interpret::GlobalId {
|
||||||
instance: self.instance,
|
instance: self.instance,
|
||||||
|
@ -1106,7 +1110,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
if fn_ret.is_ignore() {
|
if fn_ret.is_ignore() {
|
||||||
return ReturnDest::Nothing;
|
return ReturnDest::Nothing;
|
||||||
}
|
}
|
||||||
let dest = if let mir::Place::Local(index) = *dest {
|
let dest = if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dest {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(dest) => dest,
|
LocalRef::Place(dest) => dest,
|
||||||
LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
|
LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
|
||||||
|
@ -1161,7 +1165,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
src: &mir::Operand<'tcx>,
|
src: &mir::Operand<'tcx>,
|
||||||
dst: &mir::Place<'tcx>
|
dst: &mir::Place<'tcx>
|
||||||
) {
|
) {
|
||||||
if let mir::Place::Local(index) = *dst {
|
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dst {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
|
LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
|
||||||
LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
|
LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
|
||||||
|
|
|
@ -378,7 +378,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
|
|
||||||
// watch out for locals that do not have an
|
// watch out for locals that do not have an
|
||||||
// alloca; they are handled somewhat differently
|
// alloca; they are handled somewhat differently
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Operand(Some(o)) => {
|
LocalRef::Operand(Some(o)) => {
|
||||||
return Some(o);
|
return Some(o);
|
||||||
|
|
|
@ -392,7 +392,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
let cx = self.cx;
|
let cx = self.cx;
|
||||||
let tcx = self.cx.tcx();
|
let tcx = self.cx.tcx();
|
||||||
|
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(place) => {
|
LocalRef::Place(place) => {
|
||||||
return place;
|
return place;
|
||||||
|
@ -407,8 +407,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match *place {
|
let result = match *place {
|
||||||
mir::Place::Local(_) => bug!(), // handled above
|
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
|
||||||
mir::Place::Promoted(box (index, ty)) => {
|
mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let cid = mir::interpret::GlobalId {
|
let cid = mir::interpret::GlobalId {
|
||||||
instance: self.instance,
|
instance: self.instance,
|
||||||
|
@ -435,7 +435,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
|
||||||
// NB: The layout of a static may be unsized as is the case when working
|
// NB: The layout of a static may be unsized as is the case when working
|
||||||
// with a static that is an extern_type.
|
// with a static that is an extern_type.
|
||||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||||
|
@ -457,7 +457,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
cg_base.project_field(bx, field.index())
|
cg_base.project_field(bx, field.index())
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::Index(index) => {
|
mir::ProjectionElem::Index(index) => {
|
||||||
let index = &mir::Operand::Copy(mir::Place::Local(index));
|
let index = &mir::Operand::Copy(
|
||||||
|
mir::Place::Base(mir::PlaceBase::Local(index))
|
||||||
|
);
|
||||||
let index = self.codegen_operand(bx, index);
|
let index = self.codegen_operand(bx, index);
|
||||||
let llindex = index.immediate();
|
let llindex = index.immediate();
|
||||||
cg_base.project_index(bx, llindex)
|
cg_base.project_index(bx, llindex)
|
||||||
|
|
|
@ -534,7 +534,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
) -> Bx::Value {
|
) -> Bx::Value {
|
||||||
// ZST are passed as operands and require special handling
|
// ZST are passed as operands and require special handling
|
||||||
// because codegen_place() panics if Local is operand.
|
// because codegen_place() panics if Local is operand.
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
||||||
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
||||||
if let ty::Array(_, n) = op.layout.ty.sty {
|
if let ty::Array(_, n) = op.layout.ty.sty {
|
||||||
let n = n.unwrap_usize(bx.cx().tcx());
|
let n = n.unwrap_usize(bx.cx().tcx());
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
self.set_debug_loc(&mut bx, statement.source_info);
|
self.set_debug_loc(&mut bx, statement.source_info);
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(cg_dest) => {
|
LocalRef::Place(cg_dest) => {
|
||||||
self.codegen_rvalue(bx, cg_dest, rvalue)
|
self.codegen_rvalue(bx, cg_dest, rvalue)
|
||||||
|
|
|
@ -333,7 +333,7 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
|
||||||
// TEMP = &foo
|
// TEMP = &foo
|
||||||
//
|
//
|
||||||
// so extract `temp`.
|
// so extract `temp`.
|
||||||
let temp = if let &mir::Place::Local(temp) = assigned_place {
|
let temp = if let &mir::Place::Base(mir::PlaceBase::Local(temp)) = assigned_place {
|
||||||
temp
|
temp
|
||||||
} else {
|
} else {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
|
|
|
@ -8,7 +8,7 @@ use rustc::middle::region::ScopeTree;
|
||||||
use rustc::mir::{
|
use rustc::mir::{
|
||||||
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
|
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
|
||||||
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
|
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
|
||||||
Place, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
|
Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
|
||||||
TerminatorKind, VarBindingForm,
|
TerminatorKind, VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc::ty::{self, DefIdTree};
|
use rustc::ty::{self, DefIdTree};
|
||||||
|
@ -220,7 +220,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Place::Local(local) = place {
|
if let Place::Base(PlaceBase::Local(local)) = place {
|
||||||
let decl = &self.mir.local_decls[*local];
|
let decl = &self.mir.local_decls[*local];
|
||||||
err.span_label(
|
err.span_label(
|
||||||
decl.source_info.span,
|
decl.source_info.span,
|
||||||
|
@ -679,7 +679,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let borrow_span = borrow_spans.var_or_use();
|
let borrow_span = borrow_spans.var_or_use();
|
||||||
|
|
||||||
let proper_span = match *root_place {
|
let proper_span = match *root_place {
|
||||||
Place::Local(local) => self.mir.local_decls[local].source_info.span,
|
Place::Base(PlaceBase::Local(local)) => self.mir.local_decls[local].source_info.span,
|
||||||
_ => drop_span,
|
_ => drop_span,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1061,7 +1061,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
|
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
|
||||||
let local_kind = match borrow.borrowed_place {
|
let local_kind = match borrow.borrowed_place {
|
||||||
Place::Local(local) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
match self.mir.local_kind(local) {
|
match self.mir.local_kind(local) {
|
||||||
LocalKind::ReturnPointer
|
LocalKind::ReturnPointer
|
||||||
| LocalKind::Temp => bug!("temporary or return pointer with a name"),
|
| LocalKind::Temp => bug!("temporary or return pointer with a name"),
|
||||||
|
@ -1086,7 +1086,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
|
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
|
||||||
.last()
|
.last()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let local = if let Place::Local(local) = *root_place {
|
let local = if let Place::Base(PlaceBase::Local(local)) = *root_place {
|
||||||
local
|
local
|
||||||
} else {
|
} else {
|
||||||
bug!("report_cannot_return_reference_to_local: not a local")
|
bug!("report_cannot_return_reference_to_local: not a local")
|
||||||
|
@ -1385,7 +1385,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
assigned_span: Span,
|
assigned_span: Span,
|
||||||
err_place: &Place<'tcx>,
|
err_place: &Place<'tcx>,
|
||||||
) {
|
) {
|
||||||
let (from_arg, local_decl) = if let Place::Local(local) = *err_place {
|
let (from_arg, local_decl) = if let Place::Base(PlaceBase::Local(local)) = *err_place {
|
||||||
if let LocalKind::Arg = self.mir.local_kind(local) {
|
if let LocalKind::Arg = self.mir.local_kind(local) {
|
||||||
(true, Some(&self.mir.local_decls[local]))
|
(true, Some(&self.mir.local_decls[local]))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1600,13 +1600,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
including_downcast: &IncludingDowncast,
|
including_downcast: &IncludingDowncast,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Promoted(_) => {
|
Place::Base(PlaceBase::Promoted(_)) => {
|
||||||
buf.push_str("promoted");
|
buf.push_str("promoted");
|
||||||
}
|
}
|
||||||
Place::Local(local) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
self.append_local_to_string(local, buf)?;
|
self.append_local_to_string(local, buf)?;
|
||||||
}
|
}
|
||||||
Place::Static(ref static_) => {
|
Place::Base(PlaceBase::Static(ref static_)) => {
|
||||||
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
|
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
|
||||||
}
|
}
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
|
@ -1630,7 +1630,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
autoderef,
|
autoderef,
|
||||||
&including_downcast,
|
&including_downcast,
|
||||||
)?;
|
)?;
|
||||||
} else if let Place::Local(local) = proj.base {
|
} else if let Place::Base(PlaceBase::Local(local)) = proj.base {
|
||||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
|
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
|
||||||
self.mir.local_decls[local].is_user_variable
|
self.mir.local_decls[local].is_user_variable
|
||||||
{
|
{
|
||||||
|
@ -1742,12 +1742,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
/// End-user visible description of the `field`nth field of `base`
|
/// End-user visible description of the `field`nth field of `base`
|
||||||
fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
|
fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
|
||||||
match *base {
|
match *base {
|
||||||
Place::Local(local) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
let local = &self.mir.local_decls[local];
|
let local = &self.mir.local_decls[local];
|
||||||
self.describe_field_from_ty(&local.ty, field)
|
self.describe_field_from_ty(&local.ty, field)
|
||||||
}
|
}
|
||||||
Place::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field),
|
Place::Base(PlaceBase::Promoted(ref prom)) =>
|
||||||
Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field),
|
self.describe_field_from_ty(&prom.1, field),
|
||||||
|
Place::Base(PlaceBase::Static(ref static_)) =>
|
||||||
|
self.describe_field_from_ty(&static_.ty, field),
|
||||||
Place::Projection(ref proj) => match proj.elem {
|
Place::Projection(ref proj) => match proj.elem {
|
||||||
ProjectionElem::Deref => self.describe_field(&proj.base, field),
|
ProjectionElem::Deref => self.describe_field(&proj.base, field),
|
||||||
ProjectionElem::Downcast(def, variant_index) =>
|
ProjectionElem::Downcast(def, variant_index) =>
|
||||||
|
@ -1809,7 +1811,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
/// Checks if a place is a thread-local static.
|
/// Checks if a place is a thread-local static.
|
||||||
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
|
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
|
||||||
if let Place::Static(statik) = place {
|
if let Place::Base(PlaceBase::Static(statik)) = place {
|
||||||
let attrs = self.infcx.tcx.get_attrs(statik.def_id);
|
let attrs = self.infcx.tcx.get_attrs(statik.def_id);
|
||||||
let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
|
let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
|
||||||
|
|
||||||
|
@ -1827,7 +1829,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
|
fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
match place {
|
match place {
|
||||||
Place::Local(_) | Place::Static(_) | Place::Promoted(_) => {
|
Place::Base(PlaceBase::Local(_)) |
|
||||||
|
Place::Base(PlaceBase::Static(_)) |
|
||||||
|
Place::Base(PlaceBase::Promoted(_)) => {
|
||||||
StorageDeadOrDrop::LocalStorageDead
|
StorageDeadOrDrop::LocalStorageDead
|
||||||
}
|
}
|
||||||
Place::Projection(box PlaceProjection { base, elem }) => {
|
Place::Projection(box PlaceProjection { base, elem }) => {
|
||||||
|
@ -1912,7 +1916,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
// Check that the initial assignment of the reserve location is into a temporary.
|
// Check that the initial assignment of the reserve location is into a temporary.
|
||||||
let mut target = *match reservation {
|
let mut target = *match reservation {
|
||||||
Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
|
Place::Base(PlaceBase::Local(local))
|
||||||
|
if self.mir.local_kind(*local) == LocalKind::Temp => local,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1924,8 +1929,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
|
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
|
||||||
target, stmt
|
target, stmt
|
||||||
);
|
);
|
||||||
if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
|
if let StatementKind::Assign(
|
||||||
{
|
Place::Base(PlaceBase::Local(assigned_to)),
|
||||||
|
box rvalue
|
||||||
|
) = &stmt.kind {
|
||||||
debug!(
|
debug!(
|
||||||
"annotate_argument_and_return_for_borrow: assigned_to={:?} \
|
"annotate_argument_and_return_for_borrow: assigned_to={:?} \
|
||||||
rvalue={:?}",
|
rvalue={:?}",
|
||||||
|
@ -2048,7 +2055,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
target, terminator
|
target, terminator
|
||||||
);
|
);
|
||||||
if let TerminatorKind::Call {
|
if let TerminatorKind::Call {
|
||||||
destination: Some((Place::Local(assigned_to), _)),
|
destination: Some((Place::Base(PlaceBase::Local(assigned_to)), _)),
|
||||||
args,
|
args,
|
||||||
..
|
..
|
||||||
} = &terminator.kind
|
} = &terminator.kind
|
||||||
|
@ -2496,7 +2503,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
.get(location.statement_index)
|
.get(location.statement_index)
|
||||||
{
|
{
|
||||||
Some(&Statement {
|
Some(&Statement {
|
||||||
kind: StatementKind::Assign(Place::Local(local), _),
|
kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
|
||||||
..
|
..
|
||||||
}) => local,
|
}) => local,
|
||||||
_ => return OtherUse(use_span),
|
_ => return OtherUse(use_span),
|
||||||
|
@ -2522,7 +2529,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
def_id, is_generator, places
|
def_id, is_generator, places
|
||||||
);
|
);
|
||||||
if let Some((args_span, var_span)) = self.closure_span(
|
if let Some((args_span, var_span)) = self.closure_span(
|
||||||
*def_id, &Place::Local(target), places
|
*def_id, &Place::Base(PlaceBase::Local(target)), places
|
||||||
) {
|
) {
|
||||||
return ClosureUse {
|
return ClosureUse {
|
||||||
is_generator,
|
is_generator,
|
||||||
|
|
|
@ -8,7 +8,7 @@ use rustc::infer::InferCtxt;
|
||||||
use rustc::lint::builtin::UNUSED_MUT;
|
use rustc::lint::builtin::UNUSED_MUT;
|
||||||
use rustc::middle::borrowck::SignalledError;
|
use rustc::middle::borrowck::SignalledError;
|
||||||
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||||
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
|
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
|
||||||
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
|
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
|
||||||
use rustc::mir::{Terminator, TerminatorKind};
|
use rustc::mir::{Terminator, TerminatorKind};
|
||||||
use rustc::ty::query::Providers;
|
use rustc::ty::query::Providers;
|
||||||
|
@ -588,7 +588,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||||
StatementKind::StorageDead(local) => {
|
StatementKind::StorageDead(local) => {
|
||||||
self.access_place(
|
self.access_place(
|
||||||
ContextKind::StorageDead.new(location),
|
ContextKind::StorageDead.new(location),
|
||||||
(&Place::Local(local), span),
|
(&Place::Base(PlaceBase::Local(local)), span),
|
||||||
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
||||||
LocalMutationIsAllowed::Yes,
|
LocalMutationIsAllowed::Yes,
|
||||||
flow_state,
|
flow_state,
|
||||||
|
@ -1104,7 +1104,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// Special case: you can assign a immutable local variable
|
// Special case: you can assign a immutable local variable
|
||||||
// (e.g., `x = ...`) so long as it has never been initialized
|
// (e.g., `x = ...`) so long as it has never been initialized
|
||||||
// before (at this point in the flow).
|
// before (at this point in the flow).
|
||||||
if let &Place::Local(local) = place_span.0 {
|
if let &Place::Base(PlaceBase::Local(local)) = place_span.0 {
|
||||||
if let Mutability::Not = self.mir.local_decls[local].mutability {
|
if let Mutability::Not = self.mir.local_decls[local].mutability {
|
||||||
// check for reassignments to immutable local variables
|
// check for reassignments to immutable local variables
|
||||||
self.check_if_reassignment_to_immutable_state(
|
self.check_if_reassignment_to_immutable_state(
|
||||||
|
@ -1231,8 +1231,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// captures of a closure are copied/moved directly
|
// captures of a closure are copied/moved directly
|
||||||
// when generating MIR.
|
// when generating MIR.
|
||||||
match operands[field.index()] {
|
match operands[field.index()] {
|
||||||
Operand::Move(Place::Local(local))
|
Operand::Move(Place::Base(PlaceBase::Local(local)))
|
||||||
| Operand::Copy(Place::Local(local)) => {
|
| Operand::Copy(Place::Base(PlaceBase::Local(local))) => {
|
||||||
self.used_mut.insert(local);
|
self.used_mut.insert(local);
|
||||||
}
|
}
|
||||||
Operand::Move(ref place @ Place::Projection(_))
|
Operand::Move(ref place @ Place::Projection(_))
|
||||||
|
@ -1242,10 +1242,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
self.used_mut_upvars.push(field);
|
self.used_mut_upvars.push(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operand::Move(Place::Static(..))
|
Operand::Move(Place::Base(PlaceBase::Static(..)))
|
||||||
| Operand::Copy(Place::Static(..))
|
| Operand::Copy(Place::Base(PlaceBase::Static(..)))
|
||||||
| Operand::Move(Place::Promoted(..))
|
| Operand::Move(Place::Base(PlaceBase::Promoted(..)))
|
||||||
| Operand::Copy(Place::Promoted(..))
|
| Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
|
||||||
| Operand::Constant(..) => {}
|
| Operand::Constant(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1328,14 +1328,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
//
|
//
|
||||||
// FIXME: allow thread-locals to borrow other thread locals?
|
// FIXME: allow thread-locals to borrow other thread locals?
|
||||||
let (might_be_alive, will_be_dropped) = match root_place {
|
let (might_be_alive, will_be_dropped) = match root_place {
|
||||||
Place::Promoted(_) => (true, false),
|
Place::Base(PlaceBase::Promoted(_)) => (true, false),
|
||||||
Place::Static(_) => {
|
Place::Base(PlaceBase::Static(_)) => {
|
||||||
// Thread-locals might be dropped after the function exits, but
|
// Thread-locals might be dropped after the function exits, but
|
||||||
// "true" statics will never be.
|
// "true" statics will never be.
|
||||||
let is_thread_local = self.is_place_thread_local(&root_place);
|
let is_thread_local = self.is_place_thread_local(&root_place);
|
||||||
(true, is_thread_local)
|
(true, is_thread_local)
|
||||||
}
|
}
|
||||||
Place::Local(_) => {
|
Place::Base(PlaceBase::Local(_)) => {
|
||||||
// Locals are always dropped at function exit, and if they
|
// Locals are always dropped at function exit, and if they
|
||||||
// have a destructor it would've been called already.
|
// have a destructor it would've been called already.
|
||||||
(false, self.locals_are_invalidated_at_exit)
|
(false, self.locals_are_invalidated_at_exit)
|
||||||
|
@ -1594,10 +1594,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
last_prefix = prefix;
|
last_prefix = prefix;
|
||||||
}
|
}
|
||||||
match *last_prefix {
|
match *last_prefix {
|
||||||
Place::Local(_) => panic!("should have move path for every Local"),
|
Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
|
||||||
Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
|
Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Static(_) => Err(NoMovePathFound::ReachedStatic),
|
Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,8 +1623,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let mut place = place;
|
let mut place = place;
|
||||||
loop {
|
loop {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Local(_) | Place::Static(_) => {
|
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
|
||||||
// assigning to `x` does not require `x` be initialized.
|
// assigning to `x` does not require `x` be initialized.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1947,7 +1947,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
) {
|
) {
|
||||||
match root_place {
|
match root_place {
|
||||||
RootPlace {
|
RootPlace {
|
||||||
place: Place::Local(local),
|
place: Place::Base(PlaceBase::Local(local)),
|
||||||
is_local_mutation_allowed,
|
is_local_mutation_allowed,
|
||||||
} => {
|
} => {
|
||||||
// If the local may have been initialized, and it is now currently being
|
// If the local may have been initialized, and it is now currently being
|
||||||
|
@ -1972,11 +1972,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RootPlace {
|
RootPlace {
|
||||||
place: Place::Promoted(..),
|
place: Place::Base(PlaceBase::Promoted(..)),
|
||||||
is_local_mutation_allowed: _,
|
is_local_mutation_allowed: _,
|
||||||
} => {}
|
} => {}
|
||||||
RootPlace {
|
RootPlace {
|
||||||
place: Place::Static(..),
|
place: Place::Base(PlaceBase::Static(..)),
|
||||||
is_local_mutation_allowed: _,
|
is_local_mutation_allowed: _,
|
||||||
} => {}
|
} => {}
|
||||||
}
|
}
|
||||||
|
@ -1990,7 +1990,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||||
) -> Result<RootPlace<'d, 'tcx>, &'d Place<'tcx>> {
|
) -> Result<RootPlace<'d, 'tcx>, &'d Place<'tcx>> {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(local) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
let local = &self.mir.local_decls[local];
|
let local = &self.mir.local_decls[local];
|
||||||
match local.mutability {
|
match local.mutability {
|
||||||
Mutability::Not => match is_local_mutation_allowed {
|
Mutability::Not => match is_local_mutation_allowed {
|
||||||
|
@ -2012,11 +2012,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
|
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
|
||||||
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
|
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
|
||||||
Place::Promoted(_) => Ok(RootPlace {
|
Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
|
||||||
place,
|
place,
|
||||||
is_local_mutation_allowed,
|
is_local_mutation_allowed,
|
||||||
}),
|
}),
|
||||||
Place::Static(ref static_) => {
|
Place::Base(PlaceBase::Static(ref static_)) => {
|
||||||
if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
|
if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
|
||||||
Err(place)
|
Err(place)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
// If that ever stops being the case, then the ever initialized
|
// If that ever stops being the case, then the ever initialized
|
||||||
// flow could be used.
|
// flow could be used.
|
||||||
if let Some(StatementKind::Assign(
|
if let Some(StatementKind::Assign(
|
||||||
Place::Local(local),
|
Place::Base(PlaceBase::Local(local)),
|
||||||
box Rvalue::Use(Operand::Move(move_from)),
|
box Rvalue::Use(Operand::Move(move_from)),
|
||||||
)) = self.mir.basic_blocks()[location.block]
|
)) = self.mir.basic_blocks()[location.block]
|
||||||
.statements
|
.statements
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::Node;
|
use rustc::hir::Node;
|
||||||
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
|
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
|
||||||
use rustc::mir::{Mutability, Operand, Place, Projection, ProjectionElem, Static, Terminator};
|
use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
|
||||||
use rustc::mir::TerminatorKind;
|
use rustc::mir::{Terminator, TerminatorKind};
|
||||||
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
|
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
@ -45,9 +45,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
|
debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
|
||||||
|
|
||||||
match the_place_err {
|
match the_place_err {
|
||||||
Place::Local(local) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||||
if let Place::Local(_) = access_place {
|
if let Place::Base(PlaceBase::Local(_)) = access_place {
|
||||||
reason = ", as it is not declared as mutable".to_string();
|
reason = ", as it is not declared as mutable".to_string();
|
||||||
} else {
|
} else {
|
||||||
let name = self.mir.local_decls[*local]
|
let name = self.mir.local_decls[*local]
|
||||||
|
@ -78,7 +78,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
base,
|
base,
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) => {
|
}) => {
|
||||||
if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() {
|
if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
||||||
|
!self.mir.upvar_decls.is_empty() {
|
||||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||||
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
||||||
debug_assert!(is_closure_or_generator(
|
debug_assert!(is_closure_or_generator(
|
||||||
|
@ -92,7 +93,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
", as `Fn` closures cannot mutate their captured variables".to_string()
|
", as `Fn` closures cannot mutate their captured variables".to_string()
|
||||||
}
|
}
|
||||||
} else if {
|
} else if {
|
||||||
if let Place::Local(local) = *base {
|
if let Place::Base(PlaceBase::Local(local)) = *base {
|
||||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
|
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
|
||||||
= self.mir.local_decls[local].is_user_variable {
|
= self.mir.local_decls[local].is_user_variable {
|
||||||
true
|
true
|
||||||
|
@ -128,10 +129,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Place::Promoted(_) => unreachable!(),
|
Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
|
||||||
|
|
||||||
Place::Static(box Static { def_id, ty: _ }) => {
|
Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
|
||||||
if let Place::Static(_) = access_place {
|
if let Place::Base(PlaceBase::Static(_)) = access_place {
|
||||||
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
|
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
|
||||||
reason = String::new();
|
reason = String::new();
|
||||||
} else {
|
} else {
|
||||||
|
@ -241,7 +242,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Suggest removing a `&mut` from the use of a mutable reference.
|
// Suggest removing a `&mut` from the use of a mutable reference.
|
||||||
Place::Local(local)
|
Place::Base(PlaceBase::Local(local))
|
||||||
if {
|
if {
|
||||||
self.mir.local_decls.get(*local).map(|local_decl| {
|
self.mir.local_decls.get(*local).map(|local_decl| {
|
||||||
if let ClearCrossCrate::Set(
|
if let ClearCrossCrate::Set(
|
||||||
|
@ -276,7 +277,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// We want to suggest users use `let mut` for local (user
|
// We want to suggest users use `let mut` for local (user
|
||||||
// variable) mutations...
|
// variable) mutations...
|
||||||
Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
|
Place::Base(PlaceBase::Local(local))
|
||||||
|
if self.mir.local_decls[*local].can_be_made_mutable() => {
|
||||||
// ... but it doesn't make sense to suggest it on
|
// ... but it doesn't make sense to suggest it on
|
||||||
// variables that are `ref x`, `ref mut x`, `&self`,
|
// variables that are `ref x`, `ref mut x`, `&self`,
|
||||||
// or `&mut self` (such variables are simply not
|
// or `&mut self` (such variables are simply not
|
||||||
|
@ -330,7 +332,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
// complete hack to approximate old AST-borrowck
|
// complete hack to approximate old AST-borrowck
|
||||||
// diagnostic: if the span starts with a mutable borrow of
|
// diagnostic: if the span starts with a mutable borrow of
|
||||||
// a local variable, then just suggest the user remove it.
|
// a local variable, then just suggest the user remove it.
|
||||||
Place::Local(_)
|
Place::Base(PlaceBase::Local(_))
|
||||||
if {
|
if {
|
||||||
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
snippet.starts_with("&mut ")
|
snippet.starts_with("&mut ")
|
||||||
|
@ -344,7 +346,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base: Place::Local(local),
|
base: Place::Base(PlaceBase::Local(local)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) if {
|
}) if {
|
||||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
|
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
|
||||||
|
@ -368,7 +370,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
// FIXME: can this case be generalized to work for an
|
// FIXME: can this case be generalized to work for an
|
||||||
// arbitrary base for the projection?
|
// arbitrary base for the projection?
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base: Place::Local(local),
|
base: Place::Base(PlaceBase::Local(local)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) if self.mir.local_decls[*local].is_user_variable.is_some() =>
|
}) if self.mir.local_decls[*local].is_user_variable.is_some() =>
|
||||||
{
|
{
|
||||||
|
@ -447,7 +449,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base,
|
base,
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() =>
|
}) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
||||||
|
!self.mir.upvar_decls.is_empty() =>
|
||||||
{
|
{
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
err.span_help(
|
err.span_help(
|
||||||
|
@ -457,7 +460,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base: Place::Local(local),
|
base: Place::Base(PlaceBase::Local(local)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) if error_access == AccessKind::MutableBorrow => {
|
}) if error_access == AccessKind::MutableBorrow => {
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::borrow_check::nll::region_infer::values::LivenessValues;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
use rustc::mir::visit::TyContext;
|
use rustc::mir::visit::TyContext;
|
||||||
use rustc::mir::visit::Visitor;
|
use rustc::mir::visit::Visitor;
|
||||||
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
|
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, PlaceBase, Rvalue};
|
||||||
use rustc::mir::{SourceInfo, Statement, Terminator};
|
use rustc::mir::{SourceInfo, Statement, Terminator};
|
||||||
use rustc::mir::UserTypeProjection;
|
use rustc::mir::UserTypeProjection;
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
|
@ -130,7 +130,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
|
||||||
// When we see `X = ...`, then kill borrows of
|
// When we see `X = ...`, then kill borrows of
|
||||||
// `(*X).foo` and so forth.
|
// `(*X).foo` and so forth.
|
||||||
if let Some(all_facts) = self.all_facts {
|
if let Some(all_facts) = self.all_facts {
|
||||||
if let Place::Local(temp) = place {
|
if let Place::Base(PlaceBase::Local(temp)) = place {
|
||||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
|
if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
|
||||||
all_facts.killed.reserve(borrow_indices.len());
|
all_facts.killed.reserve(borrow_indices.len());
|
||||||
for &borrow_index in borrow_indices {
|
for &borrow_index in borrow_indices {
|
||||||
|
|
|
@ -6,8 +6,8 @@ use crate::borrow_check::nll::region_infer::{Cause, RegionName};
|
||||||
use crate::borrow_check::nll::ConstraintDescription;
|
use crate::borrow_check::nll::ConstraintDescription;
|
||||||
use crate::borrow_check::{Context, MirBorrowckCtxt, WriteKind};
|
use crate::borrow_check::{Context, MirBorrowckCtxt, WriteKind};
|
||||||
use rustc::mir::{
|
use rustc::mir::{
|
||||||
CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, Projection,
|
CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
|
||||||
ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
|
Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
|
||||||
};
|
};
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
@ -245,7 +245,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
Some(Cause::LiveVar(local, location)) => {
|
Some(Cause::LiveVar(local, location)) => {
|
||||||
let span = mir.source_info(location).span;
|
let span = mir.source_info(location).span;
|
||||||
let spans = self
|
let spans = self
|
||||||
.move_spans(&Place::Local(local), location)
|
.move_spans(&Place::Base(PlaceBase::Local(local)), location)
|
||||||
.or_else(|| self.borrow_spans(span, location));
|
.or_else(|| self.borrow_spans(span, location));
|
||||||
|
|
||||||
let borrow_location = context.loc;
|
let borrow_location = context.loc;
|
||||||
|
@ -265,7 +265,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let mut should_note_order = false;
|
let mut should_note_order = false;
|
||||||
if mir.local_decls[local].name.is_some() {
|
if mir.local_decls[local].name.is_some() {
|
||||||
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
|
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
|
||||||
if let Place::Local(borrowed_local) = place {
|
if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
|
||||||
let dropped_local_scope = mir.local_decls[local].visibility_scope;
|
let dropped_local_scope = mir.local_decls[local].visibility_scope;
|
||||||
let borrowed_local_scope =
|
let borrowed_local_scope =
|
||||||
mir.local_decls[*borrowed_local].visibility_scope;
|
mir.local_decls[*borrowed_local].visibility_scope;
|
||||||
|
@ -481,7 +481,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// Just point to the function, to reduce the chance of overlapping spans.
|
// Just point to the function, to reduce the chance of overlapping spans.
|
||||||
let function_span = match func {
|
let function_span = match func {
|
||||||
Operand::Constant(c) => c.span,
|
Operand::Constant(c) => c.span,
|
||||||
Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => {
|
Operand::Copy(Place::Base(PlaceBase::Local(l))) |
|
||||||
|
Operand::Move(Place::Base(PlaceBase::Local(l))) => {
|
||||||
let local_decl = &self.mir.local_decls[*l];
|
let local_decl = &self.mir.local_decls[*l];
|
||||||
if local_decl.name.is_none() {
|
if local_decl.name.is_none() {
|
||||||
local_decl.source_info.span
|
local_decl.source_info.span
|
||||||
|
@ -522,7 +523,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// it which simplifies the termination logic.
|
// it which simplifies the termination logic.
|
||||||
let mut queue = vec![location];
|
let mut queue = vec![location];
|
||||||
let mut target = if let Some(&Statement {
|
let mut target = if let Some(&Statement {
|
||||||
kind: StatementKind::Assign(Place::Local(local), _),
|
kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
|
||||||
..
|
..
|
||||||
}) = stmt
|
}) = stmt
|
||||||
{
|
{
|
||||||
|
@ -547,9 +548,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// The only kind of statement that we care about is assignments...
|
// The only kind of statement that we care about is assignments...
|
||||||
if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
|
if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
|
||||||
let into = match place {
|
let into = match place {
|
||||||
Place::Local(into) => into,
|
Place::Base(PlaceBase::Local(into)) => into,
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base: Place::Local(into),
|
base: Place::Base(PlaceBase::Local(into)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) => into,
|
}) => into,
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -563,8 +564,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// If we see a use, we should check whether it is our data, and if so
|
// If we see a use, we should check whether it is our data, and if so
|
||||||
// update the place that we're looking for to that new place.
|
// update the place that we're looking for to that new place.
|
||||||
Rvalue::Use(operand) => match operand {
|
Rvalue::Use(operand) => match operand {
|
||||||
Operand::Copy(Place::Local(from))
|
Operand::Copy(Place::Base(PlaceBase::Local(from)))
|
||||||
| Operand::Move(Place::Local(from))
|
| Operand::Move(Place::Base(PlaceBase::Local(from)))
|
||||||
if *from == target =>
|
if *from == target =>
|
||||||
{
|
{
|
||||||
target = *into;
|
target = *into;
|
||||||
|
@ -574,8 +575,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// If we see a unsized cast, then if it is our data we should check
|
// If we see a unsized cast, then if it is our data we should check
|
||||||
// whether it is being cast to a trait object.
|
// whether it is being cast to a trait object.
|
||||||
Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand {
|
Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand {
|
||||||
Operand::Copy(Place::Local(from))
|
Operand::Copy(Place::Base(PlaceBase::Local(from)))
|
||||||
| Operand::Move(Place::Local(from))
|
| Operand::Move(Place::Base(PlaceBase::Local(from)))
|
||||||
if *from == target =>
|
if *from == target =>
|
||||||
{
|
{
|
||||||
debug!("was_captured_by_trait_object: ty={:?}", ty);
|
debug!("was_captured_by_trait_object: ty={:?}", ty);
|
||||||
|
@ -605,7 +606,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
debug!("was_captured_by_trait_object: terminator={:?}", terminator);
|
debug!("was_captured_by_trait_object: terminator={:?}", terminator);
|
||||||
|
|
||||||
if let TerminatorKind::Call {
|
if let TerminatorKind::Call {
|
||||||
destination: Some((Place::Local(dest), block)),
|
destination: Some((Place::Base(PlaceBase::Local(dest)), block)),
|
||||||
args,
|
args,
|
||||||
..
|
..
|
||||||
} = &terminator.kind
|
} = &terminator.kind
|
||||||
|
@ -616,7 +617,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
// Check if one of the arguments to this function is the target place.
|
// Check if one of the arguments to this function is the target place.
|
||||||
let found_target = args.iter().any(|arg| {
|
let found_target = args.iter().any(|arg| {
|
||||||
if let Operand::Move(Place::Local(potential)) = arg {
|
if let Operand::Move(Place::Base(PlaceBase::Local(potential))) = arg {
|
||||||
*potential == target
|
*potential == target
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::borrow_check::path_utils::*;
|
||||||
use crate::dataflow::move_paths::indexes::BorrowIndex;
|
use crate::dataflow::move_paths::indexes::BorrowIndex;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::mir::visit::Visitor;
|
use rustc::mir::visit::Visitor;
|
||||||
use rustc::mir::{BasicBlock, Location, Mir, Place, Rvalue};
|
use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
|
||||||
use rustc::mir::{Statement, StatementKind};
|
use rustc::mir::{Statement, StatementKind};
|
||||||
use rustc::mir::{Terminator, TerminatorKind};
|
use rustc::mir::{Terminator, TerminatorKind};
|
||||||
use rustc::mir::{Operand, BorrowKind};
|
use rustc::mir::{Operand, BorrowKind};
|
||||||
|
@ -131,7 +131,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||||
StatementKind::StorageDead(local) => {
|
StatementKind::StorageDead(local) => {
|
||||||
self.access_place(
|
self.access_place(
|
||||||
ContextKind::StorageDead.new(location),
|
ContextKind::StorageDead.new(location),
|
||||||
&Place::Local(local),
|
&Place::Base(PlaceBase::Local(local)),
|
||||||
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
||||||
LocalMutationIsAllowed::Yes,
|
LocalMutationIsAllowed::Yes,
|
||||||
);
|
);
|
||||||
|
|
|
@ -451,10 +451,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
) -> PlaceTy<'tcx> {
|
) -> PlaceTy<'tcx> {
|
||||||
debug!("sanitize_place: {:?}", place);
|
debug!("sanitize_place: {:?}", place);
|
||||||
let place_ty = match *place {
|
let place_ty = match *place {
|
||||||
Place::Local(index) => PlaceTy::Ty {
|
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
|
||||||
ty: self.mir.local_decls[index].ty,
|
ty: self.mir.local_decls[index].ty,
|
||||||
},
|
},
|
||||||
Place::Promoted(box (_index, sty)) => {
|
Place::Base(PlaceBase::Promoted(box (_index, sty))) => {
|
||||||
let sty = self.sanitize_type(place, sty);
|
let sty = self.sanitize_type(place, sty);
|
||||||
// FIXME -- promoted MIR return types reference
|
// FIXME -- promoted MIR return types reference
|
||||||
// various "free regions" (e.g., scopes and things)
|
// various "free regions" (e.g., scopes and things)
|
||||||
|
@ -469,7 +469,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
// promoted_mir.return_ty()
|
// promoted_mir.return_ty()
|
||||||
PlaceTy::Ty { ty: sty }
|
PlaceTy::Ty { ty: sty }
|
||||||
}
|
}
|
||||||
Place::Static(box Static { def_id, ty: sty }) => {
|
Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
|
||||||
let sty = self.sanitize_type(place, sty);
|
let sty = self.sanitize_type(place, sty);
|
||||||
let ty = self.tcx().type_of(def_id);
|
let ty = self.tcx().type_of(def_id);
|
||||||
let ty = self.cx.normalize(ty, location);
|
let ty = self.cx.normalize(ty, location);
|
||||||
|
@ -553,7 +553,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProjectionElem::Index(i) => {
|
ProjectionElem::Index(i) => {
|
||||||
let index_ty = Place::Local(i).ty(self.mir, tcx).to_ty(tcx);
|
let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
|
||||||
if index_ty != tcx.types.usize {
|
if index_ty != tcx.types.usize {
|
||||||
PlaceTy::Ty {
|
PlaceTy::Ty {
|
||||||
ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
|
ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
|
||||||
|
@ -1234,7 +1234,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
// of lowering. Assignments to other sorts of places *are* interesting
|
// of lowering. Assignments to other sorts of places *are* interesting
|
||||||
// though.
|
// though.
|
||||||
let category = match *place {
|
let category = match *place {
|
||||||
Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
|
Place::Base(PlaceBase::Local(RETURN_PLACE)) => if let Some(BorrowCheckContext {
|
||||||
universal_regions:
|
universal_regions:
|
||||||
UniversalRegions {
|
UniversalRegions {
|
||||||
defining_ty: DefiningTy::Const(def_id, _),
|
defining_ty: DefiningTy::Const(def_id, _),
|
||||||
|
@ -1251,7 +1251,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
ConstraintCategory::Return
|
ConstraintCategory::Return
|
||||||
},
|
},
|
||||||
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
Place::Base(PlaceBase::Local(l))
|
||||||
|
if !mir.local_decls[l].is_user_variable.is_some() => {
|
||||||
ConstraintCategory::Boring
|
ConstraintCategory::Boring
|
||||||
}
|
}
|
||||||
_ => ConstraintCategory::Assignment,
|
_ => ConstraintCategory::Assignment,
|
||||||
|
@ -1537,7 +1538,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
Some((ref dest, _target_block)) => {
|
Some((ref dest, _target_block)) => {
|
||||||
let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
|
let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
|
||||||
let category = match *dest {
|
let category = match *dest {
|
||||||
Place::Local(RETURN_PLACE) => {
|
Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
|
||||||
if let Some(BorrowCheckContext {
|
if let Some(BorrowCheckContext {
|
||||||
universal_regions:
|
universal_regions:
|
||||||
UniversalRegions {
|
UniversalRegions {
|
||||||
|
@ -1556,7 +1557,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
ConstraintCategory::Return
|
ConstraintCategory::Return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
Place::Base(PlaceBase::Local(l))
|
||||||
|
if !mir.local_decls[l].is_user_variable.is_some() => {
|
||||||
ConstraintCategory::Boring
|
ConstraintCategory::Boring
|
||||||
}
|
}
|
||||||
_ => ConstraintCategory::Assignment,
|
_ => ConstraintCategory::Assignment,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict;
|
||||||
use crate::borrow_check::Context;
|
use crate::borrow_check::Context;
|
||||||
use crate::borrow_check::AccessDepth;
|
use crate::borrow_check::AccessDepth;
|
||||||
use crate::dataflow::indexes::BorrowIndex;
|
use crate::dataflow::indexes::BorrowIndex;
|
||||||
use rustc::mir::{BasicBlock, Location, Mir, Place};
|
use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
|
||||||
use rustc::mir::{ProjectionElem, BorrowKind};
|
use rustc::mir::{ProjectionElem, BorrowKind};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_data_structures::graph::dominators::Dominators;
|
use rustc_data_structures::graph::dominators::Dominators;
|
||||||
|
@ -138,9 +138,9 @@ pub(super) fn is_active<'tcx>(
|
||||||
/// This is called for all Yield statements on movable generators
|
/// This is called for all Yield statements on movable generators
|
||||||
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
|
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
|
||||||
match place {
|
match place {
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Static(..) => false,
|
Place::Base(PlaceBase::Static(..)) => false,
|
||||||
Place::Local(..) => true,
|
Place::Base(PlaceBase::Local(..)) => true,
|
||||||
Place::Projection(box proj) => {
|
Place::Projection(box proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
// Reborrow of already borrowed data is ignored
|
// Reborrow of already borrowed data is ignored
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::mir::ProjectionElem;
|
use rustc::mir::ProjectionElem;
|
||||||
use rustc::mir::{Local, Mir, Place, Mutability};
|
use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use crate::borrow_check::borrow_set::LocalsStateAtExit;
|
use crate::borrow_check::borrow_set::LocalsStateAtExit;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
||||||
locals_state_at_exit: &LocalsStateAtExit,
|
locals_state_at_exit: &LocalsStateAtExit,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Place::Promoted(_) => false,
|
Place::Base(PlaceBase::Promoted(_)) => false,
|
||||||
|
|
||||||
// If a local variable is immutable, then we only need to track borrows to guard
|
// If a local variable is immutable, then we only need to track borrows to guard
|
||||||
// against two kinds of errors:
|
// against two kinds of errors:
|
||||||
|
@ -40,7 +40,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
||||||
//
|
//
|
||||||
// In particular, the variable cannot be mutated -- the "access checks" will fail --
|
// In particular, the variable cannot be mutated -- the "access checks" will fail --
|
||||||
// so we don't have to worry about mutation while borrowed.
|
// so we don't have to worry about mutation while borrowed.
|
||||||
Place::Local(index) => {
|
Place::Base(PlaceBase::Local(index)) => {
|
||||||
match locals_state_at_exit {
|
match locals_state_at_exit {
|
||||||
LocalsStateAtExit::AllAreInvalidated => false,
|
LocalsStateAtExit::AllAreInvalidated => false,
|
||||||
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
|
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
|
||||||
|
@ -51,7 +51,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Place::Static(static_) => {
|
Place::Base(PlaceBase::Static(static_)) => {
|
||||||
tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
|
tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
|
||||||
}
|
}
|
||||||
Place::Projection(proj) => match proj.elem {
|
Place::Projection(proj) => match proj.elem {
|
||||||
|
@ -88,9 +88,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
||||||
loop {
|
loop {
|
||||||
match p {
|
match p {
|
||||||
Place::Projection(pi) => p = &pi.base,
|
Place::Projection(pi) => p = &pi.base,
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Static(_) => return None,
|
Place::Base(PlaceBase::Static(_)) => return None,
|
||||||
Place::Local(l) => return Some(*l),
|
Place::Base(PlaceBase::Local(l)) => return Some(*l),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@ use crate::borrow_check::ArtificialField;
|
||||||
use crate::borrow_check::Overlap;
|
use crate::borrow_check::Overlap;
|
||||||
use crate::borrow_check::{Deep, Shallow, AccessDepth};
|
use crate::borrow_check::{Deep, Shallow, AccessDepth};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::mir::{BorrowKind, Mir, Place};
|
use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
|
||||||
use rustc::mir::{Projection, ProjectionElem};
|
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
|
@ -60,8 +59,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
|
||||||
|
|
||||||
// This Local/Local case is handled by the more general code below, but
|
// This Local/Local case is handled by the more general code below, but
|
||||||
// it's so common that it's a speed win to check for it first.
|
// it's so common that it's a speed win to check for it first.
|
||||||
if let Place::Local(l1) = borrow_place {
|
if let Place::Base(PlaceBase::Local(l1)) = borrow_place {
|
||||||
if let Place::Local(l2) = access_place {
|
if let Place::Base(PlaceBase::Local(l2)) = access_place {
|
||||||
return l1 == l2;
|
return l1 == l2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,8 +338,8 @@ fn unroll_place<'tcx, R>(
|
||||||
op,
|
op,
|
||||||
),
|
),
|
||||||
|
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Local(_) | Place::Static(_) => {
|
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
|
||||||
let list = PlaceComponents {
|
let list = PlaceComponents {
|
||||||
component: place,
|
component: place,
|
||||||
next,
|
next,
|
||||||
|
@ -361,7 +360,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
|
||||||
bias: PlaceConflictBias,
|
bias: PlaceConflictBias,
|
||||||
) -> Overlap {
|
) -> Overlap {
|
||||||
match (elem1, elem2) {
|
match (elem1, elem2) {
|
||||||
(Place::Local(l1), Place::Local(l2)) => {
|
(Place::Base(PlaceBase::Local(l1)), Place::Base(PlaceBase::Local(l2))) => {
|
||||||
if l1 == l2 {
|
if l1 == l2 {
|
||||||
// the same local - base case, equal
|
// the same local - base case, equal
|
||||||
debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
|
debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
|
||||||
|
@ -372,7 +371,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
|
||||||
Overlap::Disjoint
|
Overlap::Disjoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Place::Static(static1), Place::Static(static2)) => {
|
(Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
|
||||||
if static1.def_id != static2.def_id {
|
if static1.def_id != static2.def_id {
|
||||||
debug!("place_element_conflict: DISJOINT-STATIC");
|
debug!("place_element_conflict: DISJOINT-STATIC");
|
||||||
Overlap::Disjoint
|
Overlap::Disjoint
|
||||||
|
@ -385,7 +384,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
|
||||||
Overlap::EqualOrDisjoint
|
Overlap::EqualOrDisjoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Place::Promoted(p1), Place::Promoted(p2)) => {
|
(Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
|
||||||
if p1.0 == p2.0 {
|
if p1.0 == p2.0 {
|
||||||
if let ty::Array(_, size) = p1.1.sty {
|
if let ty::Array(_, size) = p1.1.sty {
|
||||||
if size.unwrap_usize(tcx) == 0 {
|
if size.unwrap_usize(tcx) == 0 {
|
||||||
|
@ -403,9 +402,12 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
|
||||||
Overlap::Disjoint
|
Overlap::Disjoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Place::Local(_), Place::Promoted(_)) | (Place::Promoted(_), Place::Local(_)) |
|
(Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
|
||||||
(Place::Promoted(_), Place::Static(_)) | (Place::Static(_), Place::Promoted(_)) |
|
(Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
|
||||||
(Place::Local(_), Place::Static(_)) | (Place::Static(_), Place::Local(_)) => {
|
(Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
|
||||||
|
(Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
|
||||||
|
(Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
|
||||||
|
(Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
|
||||||
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
|
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
|
||||||
Overlap::Disjoint
|
Overlap::Disjoint
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use super::MirBorrowckCtxt;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::mir::{Mir, Place, ProjectionElem};
|
use rustc::mir::{Mir, Place, PlaceBase, ProjectionElem};
|
||||||
|
|
||||||
pub trait IsPrefixOf<'tcx> {
|
pub trait IsPrefixOf<'tcx> {
|
||||||
fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
|
fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
|
||||||
|
@ -26,8 +26,9 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match *cursor {
|
match *cursor {
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Local(_) | Place::Static(_) => return false,
|
Place::Base(PlaceBase::Local(_)) |
|
||||||
|
Place::Base(PlaceBase::Static(_)) => return false,
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
cursor = &proj.base;
|
cursor = &proj.base;
|
||||||
}
|
}
|
||||||
|
@ -86,9 +87,9 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
'cursor: loop {
|
'cursor: loop {
|
||||||
let proj = match *cursor {
|
let proj = match *cursor {
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Local(_) | // search yielded this leaf
|
Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
|
||||||
Place::Static(_) => {
|
Place::Base(PlaceBase::Static(_)) => {
|
||||||
self.next = None;
|
self.next = None;
|
||||||
return Some(cursor);
|
return Some(cursor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use rustc::mir::visit::{PlaceContext, Visitor};
|
use rustc::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc::mir::{BasicBlock, Local, Location, Place, Statement, StatementKind, TerminatorKind};
|
use rustc::mir::{
|
||||||
|
BasicBlock, Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind
|
||||||
|
};
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c
|
||||||
"assignment of {:?} to {:?}, adding {:?} to used mutable set",
|
"assignment of {:?} to {:?}, adding {:?} to used mutable set",
|
||||||
path.place, local, path.place
|
path.place, local, path.place
|
||||||
);
|
);
|
||||||
if let Place::Local(user_local) = path.place {
|
if let Place::Base(PlaceBase::Local(user_local)) = path.place {
|
||||||
self.mbcx.used_mut.insert(user_local);
|
self.mbcx.used_mut.insert(user_local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
Category::Place | Category::Rvalue(..) => {
|
Category::Place | Category::Rvalue(..) => {
|
||||||
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
|
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
|
||||||
block.and(Operand::Move(Place::Local(operand)))
|
block.and(Operand::Move(Place::Base(PlaceBase::Local(operand))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,19 +98,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
<,
|
<,
|
||||||
Rvalue::BinaryOp(
|
Rvalue::BinaryOp(
|
||||||
BinOp::Lt,
|
BinOp::Lt,
|
||||||
Operand::Copy(Place::Local(idx)),
|
Operand::Copy(Place::Base(PlaceBase::Local(idx))),
|
||||||
Operand::Copy(len.clone()),
|
Operand::Copy(len.clone()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let msg = BoundsCheck {
|
let msg = BoundsCheck {
|
||||||
len: Operand::Move(len),
|
len: Operand::Move(len),
|
||||||
index: Operand::Copy(Place::Local(idx)),
|
index: Operand::Copy(Place::Base(PlaceBase::Local(idx))),
|
||||||
};
|
};
|
||||||
let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
|
let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
|
||||||
success.and(slice.index(idx))
|
success.and(slice.index(idx))
|
||||||
}
|
}
|
||||||
ExprKind::SelfRef => block.and(Place::Local(Local::new(1))),
|
ExprKind::SelfRef => block.and(Place::Base(PlaceBase::Local(Local::new(1)))),
|
||||||
ExprKind::VarRef { id } => {
|
ExprKind::VarRef { id } => {
|
||||||
let place = if this.is_bound_var_in_guard(id) && this
|
let place = if this.is_bound_var_in_guard(id) && this
|
||||||
.hir
|
.hir
|
||||||
|
@ -118,17 +118,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
.all_pat_vars_are_implicit_refs_within_guards()
|
.all_pat_vars_are_implicit_refs_within_guards()
|
||||||
{
|
{
|
||||||
let index = this.var_local_id(id, RefWithinGuard);
|
let index = this.var_local_id(id, RefWithinGuard);
|
||||||
Place::Local(index).deref()
|
Place::Base(PlaceBase::Local(index)).deref()
|
||||||
} else {
|
} else {
|
||||||
let index = this.var_local_id(id, OutsideGuard);
|
let index = this.var_local_id(id, OutsideGuard);
|
||||||
Place::Local(index)
|
Place::Base(PlaceBase::Local(index))
|
||||||
};
|
};
|
||||||
block.and(place)
|
block.and(place)
|
||||||
}
|
}
|
||||||
ExprKind::StaticRef { id } => block.and(Place::Static(Box::new(Static {
|
ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
|
||||||
def_id: id,
|
def_id: id,
|
||||||
ty: expr.ty,
|
ty: expr.ty,
|
||||||
}))),
|
})))),
|
||||||
|
|
||||||
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
||||||
let place = unpack!(block = this.as_place(block, source));
|
let place = unpack!(block = this.as_place(block, source));
|
||||||
|
@ -172,14 +172,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
Statement {
|
Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::AscribeUserType(
|
kind: StatementKind::AscribeUserType(
|
||||||
Place::Local(temp.clone()),
|
Place::Base(PlaceBase::Local(temp.clone())),
|
||||||
Variance::Invariant,
|
Variance::Invariant,
|
||||||
box UserTypeProjection { base: annotation_index, projs: vec![], },
|
box UserTypeProjection { base: annotation_index, projs: vec![], },
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
block.and(Place::Local(temp))
|
block.and(Place::Base(PlaceBase::Local(temp)))
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Array { .. }
|
ExprKind::Array { .. }
|
||||||
|
@ -219,7 +219,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
});
|
});
|
||||||
let temp =
|
let temp =
|
||||||
unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
|
unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
|
||||||
block.and(Place::Local(temp))
|
block.and(Place::Base(PlaceBase::Local(temp)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
this.schedule_drop_storage_and_value(
|
this.schedule_drop_storage_and_value(
|
||||||
expr_span,
|
expr_span,
|
||||||
scope,
|
scope,
|
||||||
&Place::Local(result),
|
&Place::Base(PlaceBase::Local(result)),
|
||||||
value.ty,
|
value.ty,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -135,11 +135,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// malloc some memory of suitable type (thus far, uninitialized):
|
// malloc some memory of suitable type (thus far, uninitialized):
|
||||||
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
|
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
|
||||||
this.cfg
|
this.cfg
|
||||||
.push_assign(block, source_info, &Place::Local(result), box_);
|
.push_assign(block, source_info, &Place::Base(PlaceBase::Local(result)), box_);
|
||||||
|
|
||||||
// initialize the box contents:
|
// initialize the box contents:
|
||||||
unpack!(block = this.into(&Place::Local(result).deref(), block, value));
|
unpack!(
|
||||||
block.and(Rvalue::Use(Operand::Move(Place::Local(result))))
|
block = this.into(
|
||||||
|
&Place::Base(PlaceBase::Local(result)).deref(),
|
||||||
|
block, value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
|
||||||
}
|
}
|
||||||
ExprKind::Cast { source } => {
|
ExprKind::Cast { source } => {
|
||||||
let source = this.hir.mirror(source);
|
let source = this.hir.mirror(source);
|
||||||
|
@ -522,9 +527,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let arg_place = unpack!(block = this.as_place(block, arg));
|
let arg_place = unpack!(block = this.as_place(block, arg));
|
||||||
|
|
||||||
let mutability = match arg_place {
|
let mutability = match arg_place {
|
||||||
Place::Local(local) => this.local_decls[local].mutability,
|
Place::Base(PlaceBase::Local(local)) => this.local_decls[local].mutability,
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
base: Place::Local(local),
|
base: Place::Base(PlaceBase::Local(local)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) => {
|
}) => {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
|
@ -554,11 +559,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// Not projected from the implicit `self` in a closure.
|
// Not projected from the implicit `self` in a closure.
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
match *base {
|
match *base {
|
||||||
Place::Local(local) => local == Local::new(1),
|
Place::Base(PlaceBase::Local(local)) => local == Local::new(1),
|
||||||
Place::Projection(box Projection {
|
Place::Projection(box Projection {
|
||||||
ref base,
|
ref base,
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) => *base == Place::Local(Local::new(1)),
|
}) => *base == Place::Base(PlaceBase::Local(Local::new(1))),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
"Unexpected capture place"
|
"Unexpected capture place"
|
||||||
|
@ -583,7 +588,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
this.cfg.push_assign(
|
this.cfg.push_assign(
|
||||||
block,
|
block,
|
||||||
source_info,
|
source_info,
|
||||||
&Place::Local(temp),
|
&Place::Base(PlaceBase::Local(temp)),
|
||||||
Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place),
|
Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -594,12 +599,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
this.schedule_drop_storage_and_value(
|
this.schedule_drop_storage_and_value(
|
||||||
upvar_span,
|
upvar_span,
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
&Place::Local(temp),
|
&Place::Base(PlaceBase::Local(temp)),
|
||||||
upvar_ty,
|
upvar_ty,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.and(Operand::Move(Place::Local(temp)))
|
block.and(Operand::Move(Place::Base(PlaceBase::Local(temp))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to get a `-1` value of the appropriate type
|
// Helper to get a `-1` value of the appropriate type
|
||||||
|
|
|
@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
unpack!(block = this.into(&Place::Local(temp), block, expr));
|
unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr));
|
||||||
|
|
||||||
// In constants, temp_lifetime is None for temporaries that live for the
|
// In constants, temp_lifetime is None for temporaries that live for the
|
||||||
// 'static lifetime. Thus we do not drop these temporaries and simply leak them.
|
// 'static lifetime. Thus we do not drop these temporaries and simply leak them.
|
||||||
|
@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
this.schedule_drop_storage_and_value(
|
this.schedule_drop_storage_and_value(
|
||||||
expr_span,
|
expr_span,
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
&Place::Local(temp),
|
&Place::Base(PlaceBase::Local(temp)),
|
||||||
expr_ty,
|
expr_ty,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,7 +295,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
is_user_variable: None,
|
is_user_variable: None,
|
||||||
is_block_tail: None,
|
is_block_tail: None,
|
||||||
});
|
});
|
||||||
let ptr_temp = Place::Local(ptr_temp);
|
let ptr_temp = Place::Base(PlaceBase::Local(ptr_temp));
|
||||||
let block = unpack!(this.into(&ptr_temp, block, ptr));
|
let block = unpack!(this.into(&ptr_temp, block, ptr));
|
||||||
this.into(&ptr_temp.deref(), block, val)
|
this.into(&ptr_temp.deref(), block, val)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -139,13 +139,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
|
debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
|
||||||
this.block_context.push(BlockFrame::SubExpr);
|
this.block_context.push(BlockFrame::SubExpr);
|
||||||
let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
|
let result = unpack!(
|
||||||
|
this.into(
|
||||||
|
&Place::RETURN_PLACE,
|
||||||
|
block,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
);
|
||||||
this.block_context.pop();
|
this.block_context.pop();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
this.cfg
|
this.cfg.push_assign_unit(
|
||||||
.push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
|
block,
|
||||||
|
source_info,
|
||||||
|
&Place::RETURN_PLACE,
|
||||||
|
);
|
||||||
block
|
block
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -226,7 +235,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let temp = this.local_decls.push(local_decl);
|
let temp = this.local_decls.push(local_decl);
|
||||||
let place = Place::Local(temp);
|
let place = Place::Base(PlaceBase::Local(temp));
|
||||||
debug!("created temp {:?} for expr {:?} in block_context: {:?}",
|
debug!("created temp {:?} for expr {:?} in block_context: {:?}",
|
||||||
temp, expr, this.block_context);
|
temp, expr, this.block_context);
|
||||||
place
|
place
|
||||||
|
|
|
@ -543,7 +543,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
kind: StatementKind::StorageLive(local_id),
|
kind: StatementKind::StorageLive(local_id),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let place = Place::Local(local_id);
|
let place = Place::Base(PlaceBase::Local(local_id));
|
||||||
let var_ty = self.local_decls[local_id].ty;
|
let var_ty = self.local_decls[local_id].ty;
|
||||||
let hir_id = self.hir.tcx().hir().node_to_hir_id(var);
|
let hir_id = self.hir.tcx().hir().node_to_hir_id(var);
|
||||||
let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
|
let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
|
||||||
|
@ -559,7 +559,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
self.schedule_drop(
|
self.schedule_drop(
|
||||||
span,
|
span,
|
||||||
region_scope,
|
region_scope,
|
||||||
&Place::Local(local_id),
|
&Place::Base(PlaceBase::Local(local_id)),
|
||||||
var_ty,
|
var_ty,
|
||||||
DropKind::Value {
|
DropKind::Value {
|
||||||
cached_block: CachedBlock::default(),
|
cached_block: CachedBlock::default(),
|
||||||
|
@ -1452,7 +1452,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
self.cfg.push_assign(
|
self.cfg.push_assign(
|
||||||
block,
|
block,
|
||||||
scrutinee_source_info,
|
scrutinee_source_info,
|
||||||
&Place::Local(temp),
|
&Place::Base(PlaceBase::Local(temp)),
|
||||||
borrow,
|
borrow,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
source_info: guard_end,
|
source_info: guard_end,
|
||||||
kind: StatementKind::FakeRead(
|
kind: StatementKind::FakeRead(
|
||||||
FakeReadCause::ForMatchGuard,
|
FakeReadCause::ForMatchGuard,
|
||||||
Place::Local(temp),
|
Place::Base(PlaceBase::Local(temp)),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1529,7 +1529,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// place they refer to can't be modified by the guard.
|
// place they refer to can't be modified by the guard.
|
||||||
for binding in by_value_bindings.clone() {
|
for binding in by_value_bindings.clone() {
|
||||||
let local_id = self.var_local_id(binding.var_id, RefWithinGuard);
|
let local_id = self.var_local_id(binding.var_id, RefWithinGuard);
|
||||||
let place = Place::Local(local_id);
|
let place = Place::Base(PlaceBase::Local(local_id));
|
||||||
self.cfg.push(
|
self.cfg.push(
|
||||||
block,
|
block,
|
||||||
Statement {
|
Statement {
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
/// call `schedule_drop` once the temporary is initialized.
|
/// call `schedule_drop` once the temporary is initialized.
|
||||||
pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
|
pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
|
||||||
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
|
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
|
||||||
let place = Place::Local(temp);
|
let place = Place::Base(PlaceBase::Local(temp));
|
||||||
debug!("temp: created temp {:?} with type {:?}",
|
debug!("temp: created temp {:?} with type {:?}",
|
||||||
place, self.local_decls[temp].ty);
|
place, self.local_decls[temp].ty);
|
||||||
place
|
place
|
||||||
|
|
|
@ -741,7 +741,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
|
||||||
|
|
||||||
let mut block = START_BLOCK;
|
let mut block = START_BLOCK;
|
||||||
let expr = builder.hir.mirror(ast_expr);
|
let expr = builder.hir.mirror(ast_expr);
|
||||||
unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
|
unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
|
||||||
|
|
||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
||||||
|
@ -887,7 +887,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
for (index, arg_info) in arguments.iter().enumerate() {
|
for (index, arg_info) in arguments.iter().enumerate() {
|
||||||
// Function arguments always get the first Local indices after the return place
|
// Function arguments always get the first Local indices after the return place
|
||||||
let local = Local::new(index + 1);
|
let local = Local::new(index + 1);
|
||||||
let place = Place::Local(local);
|
let place = Place::Base(PlaceBase::Local(local));
|
||||||
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
|
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
|
||||||
|
|
||||||
// Make sure we drop (parts of) the argument even when not matched on.
|
// Make sure we drop (parts of) the argument even when not matched on.
|
||||||
|
@ -936,7 +936,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = self.hir.mirror(ast_body);
|
let body = self.hir.mirror(ast_body);
|
||||||
self.into(&Place::Local(RETURN_PLACE), block, body)
|
self.into(&Place::RETURN_PLACE, block, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
||||||
|
|
|
@ -662,7 +662,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
DropKind::Value { .. } => if !needs_drop { return },
|
DropKind::Value { .. } => if !needs_drop { return },
|
||||||
DropKind::Storage => {
|
DropKind::Storage => {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(index) => if index.index() <= self.arg_count {
|
Place::Base(PlaceBase::Local(index)) => if index.index() <= self.arg_count {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
span, "`schedule_drop` called with index {} and arg_count {}",
|
span, "`schedule_drop` called with index {} and arg_count {}",
|
||||||
index.index(),
|
index.index(),
|
||||||
|
@ -936,7 +936,7 @@ fn build_scope_drops<'tcx>(
|
||||||
// Drop the storage for both value and storage drops.
|
// Drop the storage for both value and storage drops.
|
||||||
// Only temps and vars need their storage dead.
|
// Only temps and vars need their storage dead.
|
||||||
match drop_data.location {
|
match drop_data.location {
|
||||||
Place::Local(index) if index.index() > arg_count => {
|
Place::Base(PlaceBase::Local(index)) if index.index() > arg_count => {
|
||||||
cfg.push(block, Statement {
|
cfg.push(block, Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::StorageDead(index)
|
kind: StatementKind::StorageDead(index)
|
||||||
|
|
|
@ -163,7 +163,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
|
||||||
{
|
{
|
||||||
let move_data = &ctxt.move_data;
|
let move_data = &ctxt.move_data;
|
||||||
for arg in mir.args_iter() {
|
for arg in mir.args_iter() {
|
||||||
let place = mir::Place::Local(arg);
|
let place = mir::Place::Base(mir::PlaceBase::Local(arg));
|
||||||
let lookup_result = move_data.rev_lookup.find(&place);
|
let lookup_result = move_data.rev_lookup.find(&place);
|
||||||
on_lookup_result_bits(tcx, mir, move_data,
|
on_lookup_result_bits(tcx, mir, move_data,
|
||||||
lookup_result,
|
lookup_result,
|
||||||
|
|
|
@ -92,9 +92,9 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
|
||||||
|
|
||||||
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
|
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(l) => Some(l),
|
Place::Base(PlaceBase::Local(l)) => Some(l),
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Static(..) => None,
|
Place::Base(PlaceBase::Static(..)) => None,
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
ProjectionElem::Deref => None,
|
ProjectionElem::Deref => None,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
|
use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
|
||||||
use crate::borrow_check::place_ext::PlaceExt;
|
use crate::borrow_check::place_ext::PlaceExt;
|
||||||
|
|
||||||
use rustc::mir::{self, Location, Place, Mir};
|
use rustc::mir::{self, Location, Place, PlaceBase, Mir};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::ty::RegionVid;
|
use rustc::ty::RegionVid;
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
|
||||||
) {
|
) {
|
||||||
debug!("kill_borrows_on_place: place={:?}", place);
|
debug!("kill_borrows_on_place: place={:?}", place);
|
||||||
// Handle the `Place::Local(..)` case first and exit early.
|
// Handle the `Place::Local(..)` case first and exit early.
|
||||||
if let Place::Local(local) = place {
|
if let Place::Base(PlaceBase::Local(local)) = place {
|
||||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
||||||
debug!("kill_borrows_on_place: borrow_indices={:?}", borrow_indices);
|
debug!("kill_borrows_on_place: borrow_indices={:?}", borrow_indices);
|
||||||
sets.kill_all(borrow_indices);
|
sets.kill_all(borrow_indices);
|
||||||
|
@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> {
|
||||||
mir::StatementKind::StorageDead(local) => {
|
mir::StatementKind::StorageDead(local) => {
|
||||||
// Make sure there are no remaining borrows for locals that
|
// Make sure there are no remaining borrows for locals that
|
||||||
// are gone out of scope.
|
// are gone out of scope.
|
||||||
self.kill_borrows_on_place(sets, &Place::Local(local));
|
self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
|
mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
|
||||||
|
|
|
@ -493,7 +493,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tc
|
||||||
// storagedeads after everything ends, so if we don't regard the
|
// storagedeads after everything ends, so if we don't regard the
|
||||||
// storagelive as killing storage, we would have a multiple assignment
|
// storagelive as killing storage, we would have a multiple assignment
|
||||||
// to immutable data error.
|
// to immutable data error.
|
||||||
if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
|
if let LookupResult::Exact(mpi) =
|
||||||
|
rev_lookup.find(&mir::Place::Base(mir::PlaceBase::Local(local))) {
|
||||||
debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
|
debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
|
||||||
stmt, location, &init_path_map[mpi]);
|
stmt, location, &init_path_map[mpi]);
|
||||||
sets.kill_all(&init_path_map[mpi]);
|
sets.kill_all(&init_path_map[mpi]);
|
||||||
|
|
|
@ -33,13 +33,13 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
|
||||||
moves: IndexVec::new(),
|
moves: IndexVec::new(),
|
||||||
loc_map: LocationMap::new(mir),
|
loc_map: LocationMap::new(mir),
|
||||||
rev_lookup: MovePathLookup {
|
rev_lookup: MovePathLookup {
|
||||||
locals: mir.local_decls.indices().map(Place::Local).map(|v| {
|
locals: mir.local_decls.indices().map(PlaceBase::Local).map(|v| {
|
||||||
Self::new_move_path(
|
Self::new_move_path(
|
||||||
&mut move_paths,
|
&mut move_paths,
|
||||||
&mut path_map,
|
&mut path_map,
|
||||||
&mut init_path_map,
|
&mut init_path_map,
|
||||||
None,
|
None,
|
||||||
v,
|
Place::Base(v),
|
||||||
)
|
)
|
||||||
}).collect(),
|
}).collect(),
|
||||||
projections: Default::default(),
|
projections: Default::default(),
|
||||||
|
@ -96,9 +96,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
{
|
{
|
||||||
debug!("lookup({:?})", place);
|
debug!("lookup({:?})", place);
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
|
Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
|
||||||
Place::Promoted(..) |
|
Place::Base(PlaceBase::Promoted(..)) |
|
||||||
Place::Static(..) => {
|
Place::Base(PlaceBase::Static(..)) => {
|
||||||
Err(MoveError::cannot_move_out_of(self.loc, Static))
|
Err(MoveError::cannot_move_out_of(self.loc, Static))
|
||||||
}
|
}
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
|
@ -285,7 +285,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
StatementKind::StorageLive(_) => {}
|
StatementKind::StorageLive(_) => {}
|
||||||
StatementKind::StorageDead(local) => {
|
StatementKind::StorageDead(local) => {
|
||||||
self.gather_move(&Place::Local(local));
|
self.gather_move(&Place::Base(PlaceBase::Local(local)));
|
||||||
}
|
}
|
||||||
StatementKind::SetDiscriminant{ .. } => {
|
StatementKind::SetDiscriminant{ .. } => {
|
||||||
span_bug!(stmt.source_info.span,
|
span_bug!(stmt.source_info.span,
|
||||||
|
@ -345,7 +345,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
TerminatorKind::Unreachable => { }
|
TerminatorKind::Unreachable => { }
|
||||||
|
|
||||||
TerminatorKind::Return => {
|
TerminatorKind::Return => {
|
||||||
self.gather_move(&Place::Local(RETURN_PLACE));
|
self.gather_move(&Place::RETURN_PLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminatorKind::Assert { ref cond, .. } => {
|
TerminatorKind::Assert { ref cond, .. } => {
|
||||||
|
|
|
@ -273,9 +273,9 @@ impl<'tcx> MovePathLookup<'tcx> {
|
||||||
// parent.
|
// parent.
|
||||||
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
|
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(local) => LookupResult::Exact(self.locals[local]),
|
Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
|
||||||
Place::Promoted(_) |
|
Place::Base(PlaceBase::Promoted(_)) |
|
||||||
Place::Static(..) => LookupResult::Parent(None),
|
Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
match self.find(&proj.base) {
|
match self.find(&proj.base) {
|
||||||
LookupResult::Exact(base_path) => {
|
LookupResult::Exact(base_path) => {
|
||||||
|
@ -347,7 +347,7 @@ impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
|
||||||
pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
|
pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
|
||||||
loop {
|
loop {
|
||||||
let path = &self.move_paths[mpi];
|
let path = &self.move_paths[mpi];
|
||||||
if let Place::Local(l) = path.place { return Some(l); }
|
if let Place::Base(PlaceBase::Local(l)) = path.place { return Some(l); }
|
||||||
if let Some(parent) = path.parent { mpi = parent; continue } else { return None }
|
if let Some(parent) = path.parent { mpi = parent; continue } else { return None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,9 +515,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||||
layout: Option<TyLayout<'tcx>>,
|
layout: Option<TyLayout<'tcx>>,
|
||||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place::*;
|
||||||
|
use rustc::mir::PlaceBase;
|
||||||
let op = match *mir_place {
|
let op = match *mir_place {
|
||||||
Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
|
Base(PlaceBase::Local(mir::RETURN_PLACE)) => return err!(ReadFromReturnPointer),
|
||||||
Local(local) => self.access_local(self.frame(), local, layout)?,
|
Base(PlaceBase::Local(local)) => self.access_local(self.frame(), local, layout)?,
|
||||||
|
|
||||||
Projection(ref proj) => {
|
Projection(ref proj) => {
|
||||||
let op = self.eval_place_to_op(&proj.base, None)?;
|
let op = self.eval_place_to_op(&proj.base, None)?;
|
||||||
|
|
|
@ -581,8 +581,9 @@ where
|
||||||
mir_place: &mir::Place<'tcx>
|
mir_place: &mir::Place<'tcx>
|
||||||
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place::*;
|
||||||
|
use rustc::mir::PlaceBase;
|
||||||
Ok(match *mir_place {
|
Ok(match *mir_place {
|
||||||
Promoted(ref promoted) => {
|
Base(PlaceBase::Promoted(ref promoted)) => {
|
||||||
let instance = self.frame().instance;
|
let instance = self.frame().instance;
|
||||||
self.const_eval_raw(GlobalId {
|
self.const_eval_raw(GlobalId {
|
||||||
instance,
|
instance,
|
||||||
|
@ -590,7 +591,7 @@ where
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
|
||||||
Static(ref static_) => {
|
Base(PlaceBase::Static(ref static_)) => {
|
||||||
assert!(!static_.ty.needs_subst());
|
assert!(!static_.ty.needs_subst());
|
||||||
let layout = self.layout_of(static_.ty)?;
|
let layout = self.layout_of(static_.ty)?;
|
||||||
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
|
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
|
||||||
|
@ -624,8 +625,9 @@ where
|
||||||
mir_place: &mir::Place<'tcx>
|
mir_place: &mir::Place<'tcx>
|
||||||
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
|
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place::*;
|
||||||
|
use rustc::mir::PlaceBase;
|
||||||
let place = match *mir_place {
|
let place = match *mir_place {
|
||||||
Local(mir::RETURN_PLACE) => match self.frame().return_place {
|
Base(PlaceBase::Local(mir::RETURN_PLACE)) => match self.frame().return_place {
|
||||||
Some(return_place) =>
|
Some(return_place) =>
|
||||||
// We use our layout to verify our assumption; caller will validate
|
// We use our layout to verify our assumption; caller will validate
|
||||||
// their layout on return.
|
// their layout on return.
|
||||||
|
@ -635,7 +637,7 @@ where
|
||||||
},
|
},
|
||||||
None => return err!(InvalidNullPointerUsage),
|
None => return err!(InvalidNullPointerUsage),
|
||||||
},
|
},
|
||||||
Local(local) => PlaceTy {
|
Base(PlaceBase::Local(local)) => PlaceTy {
|
||||||
place: Place::Local {
|
place: Place::Local {
|
||||||
frame: self.cur_frame(),
|
frame: self.cur_frame(),
|
||||||
local,
|
local,
|
||||||
|
|
|
@ -352,7 +352,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||||
// not advance `caller_iter` for ZSTs.
|
// not advance `caller_iter` for ZSTs.
|
||||||
let mut locals_iter = mir.args_iter();
|
let mut locals_iter = mir.args_iter();
|
||||||
while let Some(local) = locals_iter.next() {
|
while let Some(local) = locals_iter.next() {
|
||||||
let dest = self.eval_place(&mir::Place::Local(local))?;
|
let dest = self.eval_place(
|
||||||
|
&mir::Place::Base(mir::PlaceBase::Local(local))
|
||||||
|
)?;
|
||||||
if Some(local) == mir.spread_arg {
|
if Some(local) == mir.spread_arg {
|
||||||
// Must be a tuple
|
// Must be a tuple
|
||||||
for i in 0..dest.layout.fields.count() {
|
for i in 0..dest.layout.fields.count() {
|
||||||
|
@ -371,7 +373,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||||
}
|
}
|
||||||
// Don't forget to check the return type!
|
// Don't forget to check the return type!
|
||||||
if let Some(caller_ret) = dest {
|
if let Some(caller_ret) = dest {
|
||||||
let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
|
let callee_ret = self.eval_place(
|
||||||
|
&mir::Place::RETURN_PLACE
|
||||||
|
)?;
|
||||||
if !Self::check_argument_compat(
|
if !Self::check_argument_compat(
|
||||||
rust_abi,
|
rust_abi,
|
||||||
caller_ret.layout,
|
caller_ret.layout,
|
||||||
|
|
|
@ -221,7 +221,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
if let Some(..) = ty {
|
if let Some(..) = ty {
|
||||||
// The first argument (index 0), but add 1 for the return value.
|
// The first argument (index 0), but add 1 for the return value.
|
||||||
let dropee_ptr = Place::Local(Local::new(1+0));
|
let dropee_ptr = Place::Base(PlaceBase::Local(Local::new(1+0)));
|
||||||
if tcx.sess.opts.debugging_opts.mir_emit_retag {
|
if tcx.sess.opts.debugging_opts.mir_emit_retag {
|
||||||
// Function arguments should be retagged, and we make this one raw.
|
// Function arguments should be retagged, and we make this one raw.
|
||||||
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
|
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
|
||||||
|
@ -317,8 +317,8 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
|
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
|
||||||
let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span);
|
let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span);
|
||||||
|
|
||||||
let dest = Place::Local(RETURN_PLACE);
|
let dest = Place::RETURN_PLACE;
|
||||||
let src = Place::Local(Local::new(1+0)).deref();
|
let src = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
|
||||||
|
|
||||||
match self_ty.sty {
|
match self_ty.sty {
|
||||||
_ if is_copy => builder.copy_shim(),
|
_ if is_copy => builder.copy_shim(),
|
||||||
|
@ -424,10 +424,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_shim(&mut self) {
|
fn copy_shim(&mut self) {
|
||||||
let rcvr = Place::Local(Local::new(1+0)).deref();
|
let rcvr = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
|
||||||
let ret_statement = self.make_statement(
|
let ret_statement = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(RETURN_PLACE),
|
Place::RETURN_PLACE,
|
||||||
box Rvalue::Use(Operand::Copy(rcvr))
|
box Rvalue::Use(Operand::Copy(rcvr))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -436,9 +436,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
|
|
||||||
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
|
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
Place::Local(
|
Place::Base(PlaceBase::Local(
|
||||||
self.local_decls.push(temp_decl(mutability, ty, span))
|
self.local_decls.push(temp_decl(mutability, ty, span))
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_clone_call(
|
fn make_clone_call(
|
||||||
|
@ -546,7 +546,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
let inits = vec![
|
let inits = vec![
|
||||||
self.make_statement(
|
self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(beg),
|
Place::Base(PlaceBase::Local(beg)),
|
||||||
box Rvalue::Use(Operand::Constant(self.make_usize(0)))
|
box Rvalue::Use(Operand::Constant(self.make_usize(0)))
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -564,7 +564,11 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
// BB #3;
|
// BB #3;
|
||||||
// }
|
// }
|
||||||
// BB #4;
|
// BB #4;
|
||||||
self.loop_header(Place::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
|
self.loop_header(Place::Base(PlaceBase::Local(beg)),
|
||||||
|
end,
|
||||||
|
BasicBlock::new(2),
|
||||||
|
BasicBlock::new(4),
|
||||||
|
false);
|
||||||
|
|
||||||
// BB #2
|
// BB #2
|
||||||
// `dest[i] = Clone::clone(src[beg])`;
|
// `dest[i] = Clone::clone(src[beg])`;
|
||||||
|
@ -580,10 +584,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
let statements = vec![
|
let statements = vec![
|
||||||
self.make_statement(
|
self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(beg),
|
Place::Base(PlaceBase::Local(beg)),
|
||||||
box Rvalue::BinaryOp(
|
box Rvalue::BinaryOp(
|
||||||
BinOp::Add,
|
BinOp::Add,
|
||||||
Operand::Copy(Place::Local(beg)),
|
Operand::Copy(Place::Base(PlaceBase::Local(beg))),
|
||||||
Operand::Constant(self.make_usize(1))
|
Operand::Constant(self.make_usize(1))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -603,7 +607,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
|
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
|
||||||
let init = self.make_statement(
|
let init = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(beg),
|
Place::Base(PlaceBase::Local(beg)),
|
||||||
box Rvalue::Use(Operand::Constant(self.make_usize(0)))
|
box Rvalue::Use(Operand::Constant(self.make_usize(0)))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -614,7 +618,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
// BB #8;
|
// BB #8;
|
||||||
// }
|
// }
|
||||||
// BB #9;
|
// BB #9;
|
||||||
self.loop_header(Place::Local(beg), Place::Local(end),
|
self.loop_header(Place::Base(PlaceBase::Local(beg)), Place::Base(PlaceBase::Local(end)),
|
||||||
BasicBlock::new(7), BasicBlock::new(9), true);
|
BasicBlock::new(7), BasicBlock::new(9), true);
|
||||||
|
|
||||||
// BB #7 (cleanup)
|
// BB #7 (cleanup)
|
||||||
|
@ -630,10 +634,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
// `goto #6;`
|
// `goto #6;`
|
||||||
let statement = self.make_statement(
|
let statement = self.make_statement(
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(beg),
|
Place::Base(PlaceBase::Local(beg)),
|
||||||
box Rvalue::BinaryOp(
|
box Rvalue::BinaryOp(
|
||||||
BinOp::Add,
|
BinOp::Add,
|
||||||
Operand::Copy(Place::Local(beg)),
|
Operand::Copy(Place::Base(PlaceBase::Local(beg))),
|
||||||
Operand::Constant(self.make_usize(1))
|
Operand::Constant(self.make_usize(1))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -718,7 +722,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
||||||
|
|
||||||
let rcvr_arg = Local::new(1+0);
|
let rcvr_arg = Local::new(1+0);
|
||||||
let rcvr_l = Place::Local(rcvr_arg);
|
let rcvr_l = Place::Base(PlaceBase::Local(rcvr_arg));
|
||||||
let mut statements = vec![];
|
let mut statements = vec![];
|
||||||
|
|
||||||
let rcvr = match rcvr_adjustment {
|
let rcvr = match rcvr_adjustment {
|
||||||
|
@ -748,11 +752,11 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
statements.push(Statement {
|
statements.push(Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
Place::Local(ref_rcvr),
|
Place::Base(PlaceBase::Local(ref_rcvr)),
|
||||||
box Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
|
box Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
Operand::Move(Place::Local(ref_rcvr))
|
Operand::Move(Place::Base(PlaceBase::Local(ref_rcvr)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -774,12 +778,12 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
if let Some(untuple_args) = untuple_args {
|
if let Some(untuple_args) = untuple_args {
|
||||||
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
||||||
let arg_place = Place::Local(Local::new(1+1));
|
let arg_place = Place::Base(PlaceBase::Local(Local::new(1+1)));
|
||||||
Operand::Move(arg_place.field(Field::new(i), *ity))
|
Operand::Move(arg_place.field(Field::new(i), *ity))
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
args.extend((1..sig.inputs().len()).map(|i| {
|
args.extend((1..sig.inputs().len()).map(|i| {
|
||||||
Operand::Move(Place::Local(Local::new(1+i)))
|
Operand::Move(Place::Base(PlaceBase::Local(Local::new(1+i))))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,7 +801,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
block(&mut blocks, statements, TerminatorKind::Call {
|
block(&mut blocks, statements, TerminatorKind::Call {
|
||||||
func: callee,
|
func: callee,
|
||||||
args,
|
args,
|
||||||
destination: Some((Place::Local(RETURN_PLACE),
|
destination: Some((Place::RETURN_PLACE,
|
||||||
BasicBlock::new(1))),
|
BasicBlock::new(1))),
|
||||||
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
|
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
|
||||||
Some(BasicBlock::new(3))
|
Some(BasicBlock::new(3))
|
||||||
|
@ -810,7 +814,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
if let Adjustment::RefMut = rcvr_adjustment {
|
if let Adjustment::RefMut = rcvr_adjustment {
|
||||||
// BB #1 - drop for Self
|
// BB #1 - drop for Self
|
||||||
block(&mut blocks, vec![], TerminatorKind::Drop {
|
block(&mut blocks, vec![], TerminatorKind::Drop {
|
||||||
location: Place::Local(rcvr_arg),
|
location: Place::Base(PlaceBase::Local(rcvr_arg)),
|
||||||
target: BasicBlock::new(2),
|
target: BasicBlock::new(2),
|
||||||
unwind: None
|
unwind: None
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -820,7 +824,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
if let Adjustment::RefMut = rcvr_adjustment {
|
if let Adjustment::RefMut = rcvr_adjustment {
|
||||||
// BB #3 - drop if closure panics
|
// BB #3 - drop if closure panics
|
||||||
block(&mut blocks, vec![], TerminatorKind::Drop {
|
block(&mut blocks, vec![], TerminatorKind::Drop {
|
||||||
location: Place::Local(rcvr_arg),
|
location: Place::Base(PlaceBase::Local(rcvr_arg)),
|
||||||
target: BasicBlock::new(4),
|
target: BasicBlock::new(4),
|
||||||
unwind: None
|
unwind: None
|
||||||
}, true);
|
}, true);
|
||||||
|
@ -892,11 +896,11 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
statements: vec![Statement {
|
statements: vec![Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
Place::Local(RETURN_PLACE),
|
Place::RETURN_PLACE,
|
||||||
box Rvalue::Aggregate(
|
box Rvalue::Aggregate(
|
||||||
box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
|
box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
|
||||||
(1..sig.inputs().len()+1).map(|i| {
|
(1..sig.inputs().len()+1).map(|i| {
|
||||||
Operand::Move(Place::Local(Local::new(i)))
|
Operand::Move(Place::Base(PlaceBase::Local(Local::new(i))))
|
||||||
}).collect()
|
}).collect()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -121,10 +121,10 @@ fn add_move_for_packed_drop<'a, 'tcx>(
|
||||||
|
|
||||||
patch.add_statement(
|
patch.add_statement(
|
||||||
loc, StatementKind::StorageLive(temp));
|
loc, StatementKind::StorageLive(temp));
|
||||||
patch.add_assign(loc, Place::Local(temp),
|
patch.add_assign(loc, Place::Base(PlaceBase::Local(temp)),
|
||||||
Rvalue::Use(Operand::Move(location.clone())));
|
Rvalue::Use(Operand::Move(location.clone())));
|
||||||
patch.patch_terminator(loc.block, TerminatorKind::Drop {
|
patch.patch_terminator(loc.block, TerminatorKind::Drop {
|
||||||
location: Place::Local(temp),
|
location: Place::Base(PlaceBase::Local(temp)),
|
||||||
target: storage_dead_block,
|
target: storage_dead_block,
|
||||||
unwind
|
unwind
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,9 +21,9 @@ fn is_stable<'tcx>(
|
||||||
|
|
||||||
match *place {
|
match *place {
|
||||||
// Locals and statics have stable addresses, for sure
|
// Locals and statics have stable addresses, for sure
|
||||||
Local { .. } |
|
Base(PlaceBase::Local { .. }) |
|
||||||
Promoted { .. } |
|
Base(PlaceBase::Promoted { .. }) |
|
||||||
Static { .. } =>
|
Base(PlaceBase::Static { .. }) =>
|
||||||
true,
|
true,
|
||||||
// Recurse for projections
|
// Recurse for projections
|
||||||
Projection(ref proj) => {
|
Projection(ref proj) => {
|
||||||
|
@ -101,7 +101,7 @@ impl MirPass for AddRetag {
|
||||||
};
|
};
|
||||||
// Gather all arguments, skip return value.
|
// Gather all arguments, skip return value.
|
||||||
let places = local_decls.iter_enumerated().skip(1).take(arg_count)
|
let places = local_decls.iter_enumerated().skip(1).take(arg_count)
|
||||||
.map(|(local, _)| Place::Local(local))
|
.map(|(local, _)| Place::Base(PlaceBase::Local(local)))
|
||||||
.filter(needs_retag)
|
.filter(needs_retag)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
// Emit their retags.
|
// Emit their retags.
|
||||||
|
|
|
@ -241,7 +241,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let old_source_info = self.source_info;
|
let old_source_info = self.source_info;
|
||||||
if let &Place::Local(local) = base {
|
if let &Place::Base(PlaceBase::Local(local)) = base {
|
||||||
if self.mir.local_decls[local].internal {
|
if self.mir.local_decls[local].internal {
|
||||||
// Internal locals are used in the `move_val_init` desugaring.
|
// Internal locals are used in the `move_val_init` desugaring.
|
||||||
// We want to check unsafety against the source info of the
|
// We want to check unsafety against the source info of the
|
||||||
|
@ -297,13 +297,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
self.source_info = old_source_info;
|
self.source_info = old_source_info;
|
||||||
}
|
}
|
||||||
&Place::Local(..) => {
|
&Place::Base(PlaceBase::Local(..)) => {
|
||||||
// locals are safe
|
// locals are safe
|
||||||
}
|
}
|
||||||
&Place::Promoted(_) => {
|
&Place::Base(PlaceBase::Promoted(_)) => {
|
||||||
bug!("unsafety checking should happen before promotion")
|
bug!("unsafety checking should happen before promotion")
|
||||||
}
|
}
|
||||||
&Place::Static(box Static { def_id, ty: _ }) => {
|
&Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
|
||||||
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
|
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
|
||||||
self.require_unsafe("use of mutable static",
|
self.require_unsafe("use of mutable static",
|
||||||
"mutable statics can be mutated by multiple threads: aliasing violations \
|
"mutable statics can be mutated by multiple threads: aliasing violations \
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
|
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
|
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
|
||||||
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
|
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
|
||||||
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
|
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
|
||||||
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
|
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
|
||||||
|
@ -267,7 +267,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
||||||
|
|
||||||
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
|
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(loc) => self.places[loc].clone(),
|
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
|
||||||
Place::Projection(ref proj) => match proj.elem {
|
Place::Projection(ref proj) => match proj.elem {
|
||||||
ProjectionElem::Field(field, _) => {
|
ProjectionElem::Field(field, _) => {
|
||||||
trace!("field proj on {:?}", proj.base);
|
trace!("field proj on {:?}", proj.base);
|
||||||
|
@ -282,7 +282,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
||||||
// an `Index` projection would throw us off-track.
|
// an `Index` projection would throw us off-track.
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
Place::Promoted(ref promoted) => {
|
Place::Base(PlaceBase::Promoted(ref promoted)) => {
|
||||||
let generics = self.tcx.generics_of(self.source.def_id());
|
let generics = self.tcx.generics_of(self.source.def_id());
|
||||||
if generics.requires_monomorphization(self.tcx) {
|
if generics.requires_monomorphization(self.tcx) {
|
||||||
// FIXME: can't handle code with generics
|
// FIXME: can't handle code with generics
|
||||||
|
@ -556,7 +556,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
||||||
.to_ty(self.tcx);
|
.to_ty(self.tcx);
|
||||||
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
|
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
|
||||||
if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
|
if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
|
||||||
if let Place::Local(local) = *place {
|
if let Place::Base(PlaceBase::Local(local)) = *place {
|
||||||
trace!("checking whether {:?} can be stored to {:?}", value, local);
|
trace!("checking whether {:?} can be stored to {:?}", value, local);
|
||||||
if self.can_const_prop[local] {
|
if self.can_const_prop[local] {
|
||||||
trace!("storing {:?} to {:?}", value, local);
|
trace!("storing {:?} to {:?}", value, local);
|
||||||
|
@ -591,7 +591,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
||||||
while let Place::Projection(ref proj) = *place {
|
while let Place::Projection(ref proj) = *place {
|
||||||
place = &proj.base;
|
place = &proj.base;
|
||||||
}
|
}
|
||||||
if let Place::Local(local) = *place {
|
if let Place::Base(PlaceBase::Local(local)) = *place {
|
||||||
self.places[local] = None;
|
self.places[local] = None;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
|
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
|
||||||
//! future.
|
//! future.
|
||||||
|
|
||||||
use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind};
|
use rustc::mir::{
|
||||||
|
Constant, Local, LocalKind, Location, Place, PlaceBase, Mir, Operand, Rvalue, StatementKind
|
||||||
|
};
|
||||||
use rustc::mir::visit::MutVisitor;
|
use rustc::mir::visit::MutVisitor;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::{MirPass, MirSource};
|
||||||
|
@ -94,8 +96,10 @@ impl MirPass for CopyPropagation {
|
||||||
|
|
||||||
// That use of the source must be an assignment.
|
// That use of the source must be an assignment.
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::Assign(Place::Local(local), box Rvalue::Use(ref operand)) if
|
StatementKind::Assign(
|
||||||
local == dest_local => {
|
Place::Base(PlaceBase::Local(local)),
|
||||||
|
box Rvalue::Use(ref operand)
|
||||||
|
) if local == dest_local => {
|
||||||
let maybe_action = match *operand {
|
let maybe_action = match *operand {
|
||||||
Operand::Copy(ref src_place) |
|
Operand::Copy(ref src_place) |
|
||||||
Operand::Move(ref src_place) => {
|
Operand::Move(ref src_place) => {
|
||||||
|
@ -144,12 +148,12 @@ fn eliminate_self_assignments<'tcx>(
|
||||||
if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
|
if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(local),
|
Place::Base(PlaceBase::Local(local)),
|
||||||
box Rvalue::Use(Operand::Copy(Place::Local(src_local))),
|
box Rvalue::Use(Operand::Copy(Place::Base(PlaceBase::Local(src_local)))),
|
||||||
) |
|
) |
|
||||||
StatementKind::Assign(
|
StatementKind::Assign(
|
||||||
Place::Local(local),
|
Place::Base(PlaceBase::Local(local)),
|
||||||
box Rvalue::Use(Operand::Move(Place::Local(src_local))),
|
box Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(src_local)))),
|
||||||
) if local == dest_local && dest_local == src_local => {}
|
) if local == dest_local && dest_local == src_local => {}
|
||||||
_ => {
|
_ => {
|
||||||
continue;
|
continue;
|
||||||
|
@ -176,7 +180,7 @@ impl<'tcx> Action<'tcx> {
|
||||||
fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis<'_>, src_place: &Place<'tcx>)
|
fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis<'_>, src_place: &Place<'tcx>)
|
||||||
-> Option<Action<'tcx>> {
|
-> Option<Action<'tcx>> {
|
||||||
// The source must be a local.
|
// The source must be a local.
|
||||||
let src_local = if let Place::Local(local) = *src_place {
|
let src_local = if let Place::Base(PlaceBase::Local(local)) = *src_place {
|
||||||
local
|
local
|
||||||
} else {
|
} else {
|
||||||
debug!(" Can't copy-propagate local: source is not a local");
|
debug!(" Can't copy-propagate local: source is not a local");
|
||||||
|
@ -330,8 +334,8 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> {
|
||||||
self.super_operand(operand, location);
|
self.super_operand(operand, location);
|
||||||
|
|
||||||
match *operand {
|
match *operand {
|
||||||
Operand::Copy(Place::Local(local)) |
|
Operand::Copy(Place::Base(PlaceBase::Local(local))) |
|
||||||
Operand::Move(Place::Local(local)) if local == self.dest_local => {}
|
Operand::Move(Place::Base(PlaceBase::Local(local))) if local == self.dest_local => {}
|
||||||
_ => return,
|
_ => return,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -330,7 +330,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
|
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
|
||||||
self.drop_flags.get(&index).map(|t| Place::Local(*t))
|
self.drop_flags.get(&index).map(|t| Place::Base(PlaceBase::Local(*t)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// create a patch that elaborates all drops in the input
|
/// create a patch that elaborates all drops in the input
|
||||||
|
@ -543,7 +543,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
if let Some(&flag) = self.drop_flags.get(&path) {
|
if let Some(&flag) = self.drop_flags.get(&path) {
|
||||||
let span = self.patch.source_info_for_location(self.mir, loc).span;
|
let span = self.patch.source_info_for_location(self.mir, loc).span;
|
||||||
let val = self.constant_bool(span, val.value());
|
let val = self.constant_bool(span, val.value());
|
||||||
self.patch.add_assign(loc, Place::Local(flag), val);
|
self.patch.add_assign(loc, Place::Base(PlaceBase::Local(flag)), val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,7 +552,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
let span = self.patch.source_info_for_location(self.mir, loc).span;
|
let span = self.patch.source_info_for_location(self.mir, loc).span;
|
||||||
let false_ = self.constant_bool(span, false);
|
let false_ = self.constant_bool(span, false);
|
||||||
for flag in self.drop_flags.values() {
|
for flag in self.drop_flags.values() {
|
||||||
self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
|
self.patch.add_assign(loc, Place::Base(PlaceBase::Local(*flag)), false_.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
|
||||||
place: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if *place == Place::Local(self_arg()) {
|
if *place == Place::Base(PlaceBase::Local(self_arg())) {
|
||||||
*place = Place::Projection(Box::new(Projection {
|
*place = Place::Projection(Box::new(Projection {
|
||||||
base: place.clone(),
|
base: place.clone(),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
|
@ -129,7 +129,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
|
||||||
place: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if *place == Place::Local(self_arg()) {
|
if *place == Place::Base(PlaceBase::Local(self_arg())) {
|
||||||
*place = Place::Projection(Box::new(Projection {
|
*place = Place::Projection(Box::new(Projection {
|
||||||
base: place.clone(),
|
base: place.clone(),
|
||||||
elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
|
elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
|
||||||
|
@ -183,7 +183,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
// Create a Place referencing a generator struct field
|
// Create a Place referencing a generator struct field
|
||||||
fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
|
fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
|
||||||
let base = Place::Local(self_arg());
|
let base = Place::Base(PlaceBase::Local(self_arg()));
|
||||||
let field = Projection {
|
let field = Projection {
|
||||||
base: base,
|
base: base,
|
||||||
elem: ProjectionElem::Field(Field::new(idx), ty),
|
elem: ProjectionElem::Field(Field::new(idx), ty),
|
||||||
|
@ -223,7 +223,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||||
place: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if let Place::Local(l) = *place {
|
if let Place::Base(PlaceBase::Local(l)) = *place {
|
||||||
// Replace an Local in the remap with a generator struct access
|
// Replace an Local in the remap with a generator struct access
|
||||||
if let Some(&(ty, idx)) = self.remap.get(&l) {
|
if let Some(&(ty, idx)) = self.remap.get(&l) {
|
||||||
*place = self.make_field(idx, ty);
|
*place = self.make_field(idx, ty);
|
||||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||||
let ret_val = match data.terminator().kind {
|
let ret_val = match data.terminator().kind {
|
||||||
TerminatorKind::Return => Some((VariantIdx::new(1),
|
TerminatorKind::Return => Some((VariantIdx::new(1),
|
||||||
None,
|
None,
|
||||||
Operand::Move(Place::Local(self.new_ret_local)),
|
Operand::Move(Place::Base(PlaceBase::Local(self.new_ret_local))),
|
||||||
None)),
|
None)),
|
||||||
TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
|
TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
|
||||||
Some(resume),
|
Some(resume),
|
||||||
|
@ -263,7 +263,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||||
// We must assign the value first in case it gets declared dead below
|
// We must assign the value first in case it gets declared dead below
|
||||||
data.statements.push(Statement {
|
data.statements.push(Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(Place::Local(RETURN_PLACE),
|
kind: StatementKind::Assign(Place::RETURN_PLACE,
|
||||||
box self.make_state(state_idx, v)),
|
box self.make_state(state_idx, v)),
|
||||||
});
|
});
|
||||||
let state = if let Some(resume) = resume { // Yield
|
let state = if let Some(resume) = resume { // Yield
|
||||||
|
@ -597,7 +597,7 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
&Terminator {
|
&Terminator {
|
||||||
source_info,
|
source_info,
|
||||||
kind: TerminatorKind::Drop {
|
kind: TerminatorKind::Drop {
|
||||||
location: Place::Local(local),
|
location: Place::Base(PlaceBase::Local(local)),
|
||||||
target,
|
target,
|
||||||
unwind
|
unwind
|
||||||
}
|
}
|
||||||
|
@ -619,7 +619,7 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
elaborate_drop(
|
elaborate_drop(
|
||||||
&mut elaborator,
|
&mut elaborator,
|
||||||
source_info,
|
source_info,
|
||||||
&Place::Local(gen),
|
&Place::Base(PlaceBase::Local(gen)),
|
||||||
(),
|
(),
|
||||||
target,
|
target,
|
||||||
unwind,
|
unwind,
|
||||||
|
@ -693,7 +693,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||||
// Alias tracking must know we changed the type
|
// Alias tracking must know we changed the type
|
||||||
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
|
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Retag(RetagKind::Raw, Place::Local(self_arg())),
|
kind: StatementKind::Retag(RetagKind::Raw, Place::Base(PlaceBase::Local(self_arg()))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +809,7 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
|
||||||
// Create a block to destroy an unresumed generators. This can only destroy upvars.
|
// Create a block to destroy an unresumed generators. This can only destroy upvars.
|
||||||
let drop_clean = BasicBlock::new(mir.basic_blocks().len());
|
let drop_clean = BasicBlock::new(mir.basic_blocks().len());
|
||||||
let term = TerminatorKind::Drop {
|
let term = TerminatorKind::Drop {
|
||||||
location: Place::Local(self_arg()),
|
location: Place::Base(PlaceBase::Local(self_arg())),
|
||||||
target: return_block,
|
target: return_block,
|
||||||
unwind: None,
|
unwind: None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -449,7 +449,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
// Static variables need a borrow because the callee
|
// Static variables need a borrow because the callee
|
||||||
// might modify the same static.
|
// might modify the same static.
|
||||||
Place::Static(_) => true,
|
Place::Base(PlaceBase::Static(_)) => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
let temp = LocalDecl::new_temp(ty, callsite.location.span);
|
let temp = LocalDecl::new_temp(ty, callsite.location.span);
|
||||||
|
|
||||||
let tmp = caller_mir.local_decls.push(temp);
|
let tmp = caller_mir.local_decls.push(temp);
|
||||||
let tmp = Place::Local(tmp);
|
let tmp = Place::Base(PlaceBase::Local(tmp));
|
||||||
|
|
||||||
let stmt = Statement {
|
let stmt = Statement {
|
||||||
source_info: callsite.location,
|
source_info: callsite.location,
|
||||||
|
@ -560,7 +560,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
|
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
|
||||||
assert!(args.next().is_none());
|
assert!(args.next().is_none());
|
||||||
|
|
||||||
let tuple = Place::Local(tuple);
|
let tuple = Place::Base(PlaceBase::Local(tuple));
|
||||||
let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
|
let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
|
@ -599,7 +599,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
// FIXME: Analysis of the usage of the arguments to avoid
|
// FIXME: Analysis of the usage of the arguments to avoid
|
||||||
// unnecessary temporaries.
|
// unnecessary temporaries.
|
||||||
|
|
||||||
if let Operand::Move(Place::Local(local)) = arg {
|
if let Operand::Move(Place::Base(PlaceBase::Local(local))) = arg {
|
||||||
if caller_mir.local_kind(local) == LocalKind::Temp {
|
if caller_mir.local_kind(local) == LocalKind::Temp {
|
||||||
// Reuse the operand if it's a temporary already
|
// Reuse the operand if it's a temporary already
|
||||||
return local;
|
return local;
|
||||||
|
@ -617,7 +617,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
|
|
||||||
let stmt = Statement {
|
let stmt = Statement {
|
||||||
source_info: callsite.location,
|
source_info: callsite.location,
|
||||||
kind: StatementKind::Assign(Place::Local(arg_tmp), box arg),
|
kind: StatementKind::Assign(Place::Base(PlaceBase::Local(arg_tmp)), box arg),
|
||||||
};
|
};
|
||||||
caller_mir[callsite.bb].statements.push(stmt);
|
caller_mir[callsite.bb].statements.push(stmt);
|
||||||
arg_tmp
|
arg_tmp
|
||||||
|
@ -665,7 +665,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
|
||||||
_location: Location) {
|
_location: Location) {
|
||||||
if *local == RETURN_PLACE {
|
if *local == RETURN_PLACE {
|
||||||
match self.destination {
|
match self.destination {
|
||||||
Place::Local(l) => {
|
Place::Base(PlaceBase::Local(l)) => {
|
||||||
*local = l;
|
*local = l;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
@ -686,11 +686,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
|
||||||
_location: Location) {
|
_location: Location) {
|
||||||
|
|
||||||
match place {
|
match place {
|
||||||
Place::Local(RETURN_PLACE) => {
|
Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
|
||||||
// Return pointer; update the place itself
|
// Return pointer; update the place itself
|
||||||
*place = self.destination.clone();
|
*place = self.destination.clone();
|
||||||
},
|
},
|
||||||
Place::Promoted(ref mut promoted) => {
|
Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
|
||||||
if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
|
if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
|
||||||
promoted.0 = p;
|
promoted.0 = p;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Performs various peephole optimizations.
|
//! Performs various peephole optimizations.
|
||||||
|
|
||||||
use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
|
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
|
||||||
use rustc::mir::visit::{MutVisitor, Visitor};
|
use rustc::mir::visit::{MutVisitor, Visitor};
|
||||||
use rustc::ty::{TyCtxt, TyKind};
|
use rustc::ty::{TyCtxt, TyKind};
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||||
|
@ -45,7 +45,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
|
||||||
let new_place = match *rvalue {
|
let new_place = match *rvalue {
|
||||||
Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
|
Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
|
||||||
// Replace with dummy
|
// Replace with dummy
|
||||||
mem::replace(&mut projection.base, Place::Local(Local::new(0)))
|
mem::replace(&mut projection.base, Place::Base(PlaceBase::Local(Local::new(0))))
|
||||||
}
|
}
|
||||||
_ => bug!("Detected `&*` but didn't find `&*`!"),
|
_ => bug!("Detected `&*` but didn't find `&*`!"),
|
||||||
};
|
};
|
||||||
|
|
|
@ -86,13 +86,13 @@ impl Lower128Bit {
|
||||||
block.statements.push(Statement {
|
block.statements.push(Statement {
|
||||||
source_info: source_info,
|
source_info: source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
Place::Local(local),
|
Place::Base(PlaceBase::Local(local)),
|
||||||
box Rvalue::Cast(
|
box Rvalue::Cast(
|
||||||
CastKind::Misc,
|
CastKind::Misc,
|
||||||
rhs,
|
rhs,
|
||||||
rhs_override_ty.unwrap())),
|
rhs_override_ty.unwrap())),
|
||||||
});
|
});
|
||||||
rhs = Operand::Move(Place::Local(local));
|
rhs = Operand::Move(Place::Base(PlaceBase::Local(local)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_did = check_lang_item_type(
|
let call_did = check_lang_item_type(
|
||||||
|
|
|
@ -178,7 +178,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
span,
|
span,
|
||||||
scope: OUTERMOST_SOURCE_SCOPE
|
scope: OUTERMOST_SOURCE_SCOPE
|
||||||
},
|
},
|
||||||
kind: StatementKind::Assign(Place::Local(dest), box rvalue)
|
kind: StatementKind::Assign(Place::Base(PlaceBase::Local(dest)), box rvalue)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
func,
|
func,
|
||||||
args,
|
args,
|
||||||
cleanup: None,
|
cleanup: None,
|
||||||
destination: Some((Place::Local(new_temp), new_target)),
|
destination: Some(
|
||||||
|
(Place::Base(PlaceBase::Local(new_temp)), new_target)
|
||||||
|
),
|
||||||
from_hir_call,
|
from_hir_call,
|
||||||
},
|
},
|
||||||
..terminator
|
..terminator
|
||||||
|
@ -292,7 +294,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
promoted.span = span;
|
promoted.span = span;
|
||||||
promoted.local_decls[RETURN_PLACE] =
|
promoted.local_decls[RETURN_PLACE] =
|
||||||
LocalDecl::new_return_place(ty, span);
|
LocalDecl::new_return_place(ty, span);
|
||||||
Place::Promoted(box (promoted_id, ty))
|
Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
|
||||||
};
|
};
|
||||||
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
||||||
match candidate {
|
match candidate {
|
||||||
|
@ -373,7 +375,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||||
match candidate {
|
match candidate {
|
||||||
Candidate::Ref(Location { block, statement_index }) => {
|
Candidate::Ref(Location { block, statement_index }) => {
|
||||||
match mir[block].statements[statement_index].kind {
|
match mir[block].statements[statement_index].kind {
|
||||||
StatementKind::Assign(Place::Local(local), _) => {
|
StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _) => {
|
||||||
if temps[local] == TempState::PromotedOut {
|
if temps[local] == TempState::PromotedOut {
|
||||||
// Already promoted.
|
// Already promoted.
|
||||||
continue;
|
continue;
|
||||||
|
@ -420,7 +422,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||||
for block in mir.basic_blocks_mut() {
|
for block in mir.basic_blocks_mut() {
|
||||||
block.statements.retain(|statement| {
|
block.statements.retain(|statement| {
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::Assign(Place::Local(index), _) |
|
StatementKind::Assign(Place::Base(PlaceBase::Local(index)), _) |
|
||||||
StatementKind::StorageLive(index) |
|
StatementKind::StorageLive(index) |
|
||||||
StatementKind::StorageDead(index) => {
|
StatementKind::StorageDead(index) => {
|
||||||
!promoted(index)
|
!promoted(index)
|
||||||
|
@ -430,7 +432,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||||
});
|
});
|
||||||
let terminator = block.terminator_mut();
|
let terminator = block.terminator_mut();
|
||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
|
TerminatorKind::Drop { location: Place::Base(PlaceBase::Local(index)), target, .. } => {
|
||||||
if promoted(index) {
|
if promoted(index) {
|
||||||
terminator.kind = TerminatorKind::Goto {
|
terminator.kind = TerminatorKind::Goto {
|
||||||
target,
|
target,
|
||||||
|
|
|
@ -186,9 +186,9 @@ trait Qualif {
|
||||||
|
|
||||||
fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
|
fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(local) => Self::in_local(cx, local),
|
Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
|
||||||
Place::Promoted(_) => bug!("qualifying already promoted MIR"),
|
Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
|
||||||
Place::Static(ref static_) => Self::in_static(cx, static_),
|
Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
|
||||||
Place::Projection(ref proj) => Self::in_projection(cx, proj),
|
Place::Projection(ref proj) => Self::in_projection(cx, proj),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -730,7 +730,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
place = &proj.base;
|
place = &proj.base;
|
||||||
}
|
}
|
||||||
debug!("qualify_consts: promotion candidate: place={:?}", place);
|
debug!("qualify_consts: promotion candidate: place={:?}", place);
|
||||||
if let Place::Local(local) = *place {
|
if let Place::Base(PlaceBase::Local(local)) = *place {
|
||||||
if self.mir.local_kind(local) == LocalKind::Temp {
|
if self.mir.local_kind(local) == LocalKind::Temp {
|
||||||
debug!("qualify_consts: promotion candidate: local={:?}", local);
|
debug!("qualify_consts: promotion candidate: local={:?}", local);
|
||||||
// The borrowed place doesn't have `HasMutInterior`
|
// The borrowed place doesn't have `HasMutInterior`
|
||||||
|
@ -754,7 +754,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
let index = loop {
|
let index = loop {
|
||||||
match dest {
|
match dest {
|
||||||
// We treat all locals equal in constants
|
// We treat all locals equal in constants
|
||||||
Place::Local(index) => break *index,
|
Place::Base(PlaceBase::Local(index)) => break *index,
|
||||||
// projections are transparent for assignments
|
// projections are transparent for assignments
|
||||||
// we qualify the entire destination at once, even if just a field would have
|
// we qualify the entire destination at once, even if just a field would have
|
||||||
// stricter qualification
|
// stricter qualification
|
||||||
|
@ -768,8 +768,9 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
dest = &proj.base;
|
dest = &proj.base;
|
||||||
},
|
},
|
||||||
Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
|
Place::Base(PlaceBase::Promoted(..)) =>
|
||||||
Place::Static(..) => {
|
bug!("promoteds don't exist yet during promotion"),
|
||||||
|
Place::Base(PlaceBase::Static(..)) => {
|
||||||
// Catch more errors in the destination. `visit_place` also checks that we
|
// Catch more errors in the destination. `visit_place` also checks that we
|
||||||
// do not try to access statics from constants or try to mutate statics
|
// do not try to access statics from constants or try to mutate statics
|
||||||
self.visit_place(
|
self.visit_place(
|
||||||
|
@ -878,7 +879,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
match *candidate {
|
match *candidate {
|
||||||
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
|
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
|
||||||
match self.mir[bb].statements[stmt_idx].kind {
|
match self.mir[bb].statements[stmt_idx].kind {
|
||||||
StatementKind::Assign(_, box Rvalue::Ref(_, _, Place::Local(index))) => {
|
StatementKind::Assign(
|
||||||
|
_,
|
||||||
|
box Rvalue::Ref(_, _, Place::Base(PlaceBase::Local(index)))
|
||||||
|
) => {
|
||||||
promoted_temps.insert(index);
|
promoted_temps.insert(index);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -915,9 +919,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||||
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
|
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
|
||||||
self.super_place(place, context, location);
|
self.super_place(place, context, location);
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(_) |
|
Place::Base(PlaceBase::Local(_)) |
|
||||||
Place::Promoted(_) => {}
|
Place::Base(PlaceBase::Promoted(_)) => {}
|
||||||
Place::Static(ref global) => {
|
Place::Base(PlaceBase::Static(ref global)) => {
|
||||||
if self.tcx
|
if self.tcx
|
||||||
.get_attrs(global.def_id)
|
.get_attrs(global.def_id)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1032,7 +1036,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||||
match *operand {
|
match *operand {
|
||||||
Operand::Move(ref place) => {
|
Operand::Move(ref place) => {
|
||||||
// Mark the consumed locals to indicate later drops are noops.
|
// Mark the consumed locals to indicate later drops are noops.
|
||||||
if let Place::Local(local) = *place {
|
if let Place::Base(PlaceBase::Local(local)) = *place {
|
||||||
self.cx.per_local[NeedsDrop].remove(local);
|
self.cx.per_local[NeedsDrop].remove(local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1335,7 +1339,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||||
unleash_miri!(self);
|
unleash_miri!(self);
|
||||||
// HACK(eddyb): emulate a bit of dataflow analysis,
|
// HACK(eddyb): emulate a bit of dataflow analysis,
|
||||||
// conservatively, that drop elaboration will do.
|
// conservatively, that drop elaboration will do.
|
||||||
let needs_drop = if let Place::Local(local) = *place {
|
let needs_drop = if let Place::Base(PlaceBase::Local(local)) = *place {
|
||||||
if NeedsDrop::in_local(self, local) {
|
if NeedsDrop::in_local(self, local) {
|
||||||
Some(self.mir.local_decls[local].source_info.span)
|
Some(self.mir.local_decls[local].source_info.span)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1565,7 +1569,11 @@ impl MirPass for QualifyAndPromoteConstants {
|
||||||
});
|
});
|
||||||
let terminator = block.terminator_mut();
|
let terminator = block.terminator_mut();
|
||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
|
TerminatorKind::Drop {
|
||||||
|
location: Place::Base(PlaceBase::Local(index)),
|
||||||
|
target,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
if promoted_temps.contains(index) {
|
if promoted_temps.contains(index) {
|
||||||
terminator.kind = TerminatorKind::Goto {
|
terminator.kind = TerminatorKind::Goto {
|
||||||
target,
|
target,
|
||||||
|
|
|
@ -252,10 +252,11 @@ fn check_place(
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> McfResult {
|
) -> McfResult {
|
||||||
match place {
|
match place {
|
||||||
Place::Local(_) => Ok(()),
|
Place::Base(PlaceBase::Local(_)) => Ok(()),
|
||||||
// promoteds are always fine, they are essentially constants
|
// promoteds are always fine, they are essentially constants
|
||||||
Place::Promoted(_) => Ok(()),
|
Place::Base(PlaceBase::Promoted(_)) => Ok(()),
|
||||||
Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
|
Place::Base(PlaceBase::Static(_)) =>
|
||||||
|
Err((span, "cannot access `static` items in const fn".into())),
|
||||||
Place::Projection(proj) => {
|
Place::Projection(proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
|
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl RemoveNoopLandingPads {
|
||||||
// These are all nops in a landing pad
|
// These are all nops in a landing pad
|
||||||
}
|
}
|
||||||
|
|
||||||
StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => {
|
StatementKind::Assign(Place::Base(PlaceBase::Local(_)), box Rvalue::Use(_)) => {
|
||||||
// Writing to a local (e.g., a drop flag) does not
|
// Writing to a local (e.g., a drop flag) does not
|
||||||
// turn a landing pad to a non-nop
|
// turn a landing pad to a non-nop
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
assert!(args.len() == 1);
|
assert!(args.len() == 1);
|
||||||
let peek_arg_place = match args[0] {
|
let peek_arg_place = match args[0] {
|
||||||
mir::Operand::Copy(ref place @ mir::Place::Local(_)) |
|
mir::Operand::Copy(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) |
|
||||||
mir::Operand::Move(ref place @ mir::Place::Local(_)) => Some(place),
|
mir::Operand::Move(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) => Some(place),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
|
||||||
let temp = self.patch.new_temp(item_ty, self.mir.source_info(location).span);
|
let temp = self.patch.new_temp(item_ty, self.mir.source_info(location).span);
|
||||||
self.patch.add_statement(location, StatementKind::StorageLive(temp));
|
self.patch.add_statement(location, StatementKind::StorageLive(temp));
|
||||||
self.patch.add_assign(location,
|
self.patch.add_assign(location,
|
||||||
Place::Local(temp),
|
Place::Base(PlaceBase::Local(temp)),
|
||||||
Rvalue::Use(
|
Rvalue::Use(
|
||||||
Operand::Move(
|
Operand::Move(
|
||||||
Place::Projection(box PlaceProjection{
|
Place::Projection(box PlaceProjection{
|
||||||
|
@ -113,12 +113,16 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
|
||||||
}))));
|
}))));
|
||||||
temp
|
temp
|
||||||
}).collect();
|
}).collect();
|
||||||
self.patch.add_assign(location,
|
self.patch.add_assign(
|
||||||
dst_place.clone(),
|
location,
|
||||||
Rvalue::Aggregate(box AggregateKind::Array(item_ty),
|
dst_place.clone(),
|
||||||
temps.iter().map(
|
Rvalue::Aggregate(
|
||||||
|x| Operand::Move(Place::Local(*x))).collect()
|
box AggregateKind::Array(item_ty),
|
||||||
));
|
temps.iter().map(
|
||||||
|
|x| Operand::Move(Place::Base(PlaceBase::Local(*x)))
|
||||||
|
).collect()
|
||||||
|
)
|
||||||
|
);
|
||||||
for temp in temps {
|
for temp in temps {
|
||||||
self.patch.add_statement(location, StatementKind::StorageDead(temp));
|
self.patch.add_statement(location, StatementKind::StorageDead(temp));
|
||||||
}
|
}
|
||||||
|
@ -176,7 +180,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
|
||||||
if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind {
|
if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind {
|
||||||
if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = **rval {
|
if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = **rval {
|
||||||
let items : Vec<_> = items.iter().map(|item| {
|
let items : Vec<_> = items.iter().map(|item| {
|
||||||
if let Operand::Move(Place::Local(local)) = item {
|
if let Operand::Move(Place::Base(PlaceBase::Local(local))) = item {
|
||||||
let local_use = &visitor.locals_use[*local];
|
let local_use = &visitor.locals_use[*local];
|
||||||
let opt_index_and_place = Self::try_get_item_source(local_use, mir);
|
let opt_index_and_place = Self::try_get_item_source(local_use, mir);
|
||||||
// each local should be used twice:
|
// each local should be used twice:
|
||||||
|
@ -257,7 +261,7 @@ impl RestoreSubsliceArrayMoveOut {
|
||||||
if block.statements.len() > location.statement_index {
|
if block.statements.len() > location.statement_index {
|
||||||
let statement = &block.statements[location.statement_index];
|
let statement = &block.statements[location.statement_index];
|
||||||
if let StatementKind::Assign(
|
if let StatementKind::Assign(
|
||||||
Place::Local(_),
|
Place::Base(PlaceBase::Local(_)),
|
||||||
box Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
|
box Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
|
||||||
ref base, elem: ProjectionElem::ConstantIndex{
|
ref base, elem: ProjectionElem::ConstantIndex{
|
||||||
offset, min_length: _, from_end: false}})))) = statement.kind {
|
offset, min_length: _, from_end: false}})))) = statement.kind {
|
||||||
|
|
|
@ -486,7 +486,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
// discriminant after it is free-ed, because that
|
// discriminant after it is free-ed, because that
|
||||||
// way lies only trouble.
|
// way lies only trouble.
|
||||||
let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
|
let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
|
||||||
let discr = Place::Local(self.new_temp(discr_ty));
|
let discr = Place::Base(PlaceBase::Local(self.new_temp(discr_ty)));
|
||||||
let discr_rv = Rvalue::Discriminant(self.place.clone());
|
let discr_rv = Rvalue::Discriminant(self.place.clone());
|
||||||
let switch_block = BasicBlockData {
|
let switch_block = BasicBlockData {
|
||||||
statements: vec![self.assign(&discr, discr_rv)],
|
statements: vec![self.assign(&discr, discr_rv)],
|
||||||
|
@ -520,11 +520,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
mutbl: hir::Mutability::MutMutable
|
mutbl: hir::Mutability::MutMutable
|
||||||
});
|
});
|
||||||
let ref_place = self.new_temp(ref_ty);
|
let ref_place = self.new_temp(ref_ty);
|
||||||
let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
|
let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
|
||||||
|
|
||||||
let result = BasicBlockData {
|
let result = BasicBlockData {
|
||||||
statements: vec![self.assign(
|
statements: vec![self.assign(
|
||||||
&Place::Local(ref_place),
|
&Place::Base(PlaceBase::Local(ref_place)),
|
||||||
Rvalue::Ref(tcx.types.re_erased,
|
Rvalue::Ref(tcx.types.re_erased,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||||
self.place.clone())
|
self.place.clone())
|
||||||
|
@ -533,7 +533,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
kind: TerminatorKind::Call {
|
kind: TerminatorKind::Call {
|
||||||
func: Operand::function_handle(tcx, drop_fn.def_id, substs,
|
func: Operand::function_handle(tcx, drop_fn.def_id, substs,
|
||||||
self.source_info.span),
|
self.source_info.span),
|
||||||
args: vec![Operand::Move(Place::Local(ref_place))],
|
args: vec![Operand::Move(Place::Base(PlaceBase::Local(ref_place)))],
|
||||||
destination: Some((unit_temp, succ)),
|
destination: Some((unit_temp, succ)),
|
||||||
cleanup: unwind.into_option(),
|
cleanup: unwind.into_option(),
|
||||||
from_hir_call: true,
|
from_hir_call: true,
|
||||||
|
@ -578,8 +578,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
ty: ety,
|
ty: ety,
|
||||||
mutbl: hir::Mutability::MutMutable
|
mutbl: hir::Mutability::MutMutable
|
||||||
});
|
});
|
||||||
let ptr = &Place::Local(self.new_temp(ref_ty));
|
let ptr = &Place::Base(PlaceBase::Local(self.new_temp(ref_ty)));
|
||||||
let can_go = &Place::Local(self.new_temp(tcx.types.bool));
|
let can_go = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
|
||||||
|
|
||||||
let one = self.constant_usize(1);
|
let one = self.constant_usize(1);
|
||||||
let (ptr_next, cur_next) = if ptr_based {
|
let (ptr_next, cur_next) = if ptr_based {
|
||||||
|
@ -587,23 +587,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
tcx.types.re_erased,
|
tcx.types.re_erased,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||||
Place::Projection(Box::new(Projection {
|
Place::Projection(Box::new(Projection {
|
||||||
base: Place::Local(cur),
|
base: Place::Base(PlaceBase::Local(cur)),
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}))
|
}))
|
||||||
),
|
),
|
||||||
Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one))
|
Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one))
|
||||||
} else {
|
} else {
|
||||||
(Rvalue::Ref(
|
(Rvalue::Ref(
|
||||||
tcx.types.re_erased,
|
tcx.types.re_erased,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||||
self.place.clone().index(cur)),
|
self.place.clone().index(cur)),
|
||||||
Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
|
Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one))
|
||||||
};
|
};
|
||||||
|
|
||||||
let drop_block = BasicBlockData {
|
let drop_block = BasicBlockData {
|
||||||
statements: vec![
|
statements: vec![
|
||||||
self.assign(ptr, ptr_next),
|
self.assign(ptr, ptr_next),
|
||||||
self.assign(&Place::Local(cur), cur_next)
|
self.assign(&Place::Base(PlaceBase::Local(cur)), cur_next)
|
||||||
],
|
],
|
||||||
is_cleanup: unwind.is_cleanup(),
|
is_cleanup: unwind.is_cleanup(),
|
||||||
terminator: Some(Terminator {
|
terminator: Some(Terminator {
|
||||||
|
@ -617,7 +617,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let loop_block = BasicBlockData {
|
let loop_block = BasicBlockData {
|
||||||
statements: vec![
|
statements: vec![
|
||||||
self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
|
self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
|
||||||
copy(&Place::Local(cur)),
|
copy(&Place::Base(PlaceBase::Local(cur))),
|
||||||
copy(length_or_end)))
|
copy(length_or_end)))
|
||||||
],
|
],
|
||||||
is_cleanup: unwind.is_cleanup(),
|
is_cleanup: unwind.is_cleanup(),
|
||||||
|
@ -667,8 +667,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
|
|
||||||
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
|
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let size = &Place::Local(self.new_temp(tcx.types.usize));
|
let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
|
||||||
let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
|
let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
|
||||||
let base_block = BasicBlockData {
|
let base_block = BasicBlockData {
|
||||||
statements: vec![
|
statements: vec![
|
||||||
self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
|
self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
|
||||||
|
@ -703,9 +703,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
};
|
};
|
||||||
|
|
||||||
let cur = self.new_temp(iter_ty);
|
let cur = self.new_temp(iter_ty);
|
||||||
let length = Place::Local(self.new_temp(tcx.types.usize));
|
let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
|
||||||
let length_or_end = if ptr_based {
|
let length_or_end = if ptr_based {
|
||||||
Place::Local(self.new_temp(iter_ty))
|
// FIXME check if we want to make it return a `Place` directly
|
||||||
|
// if all use sites want a `Place::Base` anyway.
|
||||||
|
let temp = self.new_temp(iter_ty);
|
||||||
|
Place::Base(PlaceBase::Local(temp))
|
||||||
} else {
|
} else {
|
||||||
length.clone()
|
length.clone()
|
||||||
};
|
};
|
||||||
|
@ -728,13 +731,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
unwind,
|
unwind,
|
||||||
ptr_based);
|
ptr_based);
|
||||||
|
|
||||||
let cur = Place::Local(cur);
|
let cur = Place::Base(PlaceBase::Local(cur));
|
||||||
let zero = self.constant_usize(0);
|
let zero = self.constant_usize(0);
|
||||||
let mut drop_block_stmts = vec![];
|
let mut drop_block_stmts = vec![];
|
||||||
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
|
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
|
||||||
if ptr_based {
|
if ptr_based {
|
||||||
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
|
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
|
||||||
let tmp = Place::Local(self.new_temp(tmp_ty));
|
let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty)));
|
||||||
// tmp = &mut P;
|
// tmp = &mut P;
|
||||||
// cur = tmp as *mut T;
|
// cur = tmp as *mut T;
|
||||||
// end = Offset(cur, len);
|
// end = Offset(cur, len);
|
||||||
|
@ -883,7 +886,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
unwind: Unwind
|
unwind: Unwind
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
|
let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
|
||||||
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
|
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
|
||||||
let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
|
let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
|
||||||
let field = Field::new(i);
|
let field = Field::new(i);
|
||||||
|
|
|
@ -134,7 +134,11 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
write!(w, ", ")?;
|
write!(w, ", ")?;
|
||||||
}
|
}
|
||||||
write!(w, "{:?}: {}", Place::Local(arg), escape(&mir.local_decls[arg].ty))?;
|
write!(w,
|
||||||
|
"{:?}: {}",
|
||||||
|
Place::Base(PlaceBase::Local(arg)),
|
||||||
|
escape(&mir.local_decls[arg].ty)
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(w, ") -> {}", escape(mir.return_ty()))?;
|
write!(w, ") -> {}", escape(mir.return_ty()))?;
|
||||||
|
@ -150,10 +154,10 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
if let Some(name) = decl.name {
|
if let Some(name) = decl.name {
|
||||||
write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
|
write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
|
||||||
Place::Local(local), escape(&decl.ty), name)?;
|
Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?;
|
||||||
} else {
|
} else {
|
||||||
write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
|
write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
|
||||||
Place::Local(local), escape(&decl.ty))?;
|
Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -625,7 +625,7 @@ fn write_mir_sig(
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
write!(w, ", ")?;
|
write!(w, ", ")?;
|
||||||
}
|
}
|
||||||
write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
|
write!(w, "{:?}: {}", Place::Base(PlaceBase::Local(arg)), mir.local_decls[arg].ty)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(w, ") -> {}", mir.return_ty())?;
|
write!(w, ") -> {}", mir.return_ty())?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue