Skip to content

Commit

Permalink
Auto merge of #44308 - eddyb:local-index, r=arielb1
Browse files Browse the repository at this point in the history
[MIR] Restrict ProjectionElem::Index and Storage{Live,Dead} to Local.

(see #44285)

r? @nikomatsakis
  • Loading branch information
bors committed Sep 5, 2017
2 parents 2f681bf + e74f96e commit 2f1ef9e
Show file tree
Hide file tree
Showing 27 changed files with 319 additions and 362 deletions.
24 changes: 12 additions & 12 deletions src/librustc/mir/mod.rs
Expand Up @@ -901,10 +901,10 @@ pub enum StatementKind<'tcx> {
SetDiscriminant { lvalue: Lvalue<'tcx>, variant_index: usize },

/// Start a live range for the storage of the local.
StorageLive(Lvalue<'tcx>),
StorageLive(Local),

/// End the current live range for the storage of the local.
StorageDead(Lvalue<'tcx>),
StorageDead(Local),

/// Execute a piece of inline Assembly.
InlineAsm {
Expand Down Expand Up @@ -1077,12 +1077,12 @@ pub enum ProjectionElem<'tcx, V, T> {
}

/// Alias for projections as they appear in lvalues, where the base is an lvalue
/// and the index is an operand.
pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Operand<'tcx>, Ty<'tcx>>;
/// and the index is a local.
pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx>>;

/// Alias for projections as they appear in lvalues, where the base is an lvalue
/// and the index is an operand.
pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Operand<'tcx>, Ty<'tcx>>;
/// and the index is a local.
pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;

newtype_index!(Field, "field");

Expand All @@ -1099,7 +1099,7 @@ impl<'tcx> Lvalue<'tcx> {
self.elem(ProjectionElem::Downcast(adt_def, variant_index))
}

pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> {
pub fn index(self, index: Local) -> Lvalue<'tcx> {
self.elem(ProjectionElem::Index(index))
}

Expand Down Expand Up @@ -1701,8 +1701,8 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
lvalue: lvalue.fold_with(folder),
variant_index,
},
StorageLive(ref lval) => StorageLive(lval.fold_with(folder)),
StorageDead(ref lval) => StorageDead(lval.fold_with(folder)),
StorageLive(ref local) => StorageLive(local.fold_with(folder)),
StorageDead(ref local) => StorageDead(local.fold_with(folder)),
InlineAsm { ref asm, ref outputs, ref inputs } => InlineAsm {
asm: asm.clone(),
outputs: outputs.fold_with(folder),
Expand Down Expand Up @@ -1732,9 +1732,9 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {

match self.kind {
Assign(ref lval, ref rval) => { lval.visit_with(visitor) || rval.visit_with(visitor) }
SetDiscriminant { ref lvalue, .. } |
StorageLive(ref lvalue) |
StorageDead(ref lvalue) => lvalue.visit_with(visitor),
SetDiscriminant { ref lvalue, .. } => lvalue.visit_with(visitor),
StorageLive(ref local) |
StorageDead(ref local) => local.visit_with(visitor),
InlineAsm { ref outputs, ref inputs, .. } =>
outputs.visit_with(visitor) || inputs.visit_with(visitor),

Expand Down
18 changes: 10 additions & 8 deletions src/librustc/mir/visit.rs
Expand Up @@ -256,7 +256,9 @@ macro_rules! make_mir_visitor {
}

fn visit_local(&mut self,
_local: & $($mutability)* Local) {
_local: & $($mutability)* Local,
_context: LvalueContext<'tcx>,
_location: Location) {
}

fn visit_visibility_scope(&mut self,
Expand Down Expand Up @@ -358,11 +360,11 @@ macro_rules! make_mir_visitor {
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
self.visit_lvalue(lvalue, LvalueContext::Store, location);
}
StatementKind::StorageLive(ref $($mutability)* lvalue) => {
self.visit_lvalue(lvalue, LvalueContext::StorageLive, location);
StatementKind::StorageLive(ref $($mutability)* local) => {
self.visit_local(local, LvalueContext::StorageLive, location);
}
StatementKind::StorageDead(ref $($mutability)* lvalue) => {
self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
StatementKind::StorageDead(ref $($mutability)* local) => {
self.visit_local(local, LvalueContext::StorageDead, location);
}
StatementKind::InlineAsm { ref $($mutability)* outputs,
ref $($mutability)* inputs,
Expand Down Expand Up @@ -610,7 +612,7 @@ macro_rules! make_mir_visitor {
location: Location) {
match *lvalue {
Lvalue::Local(ref $($mutability)* local) => {
self.visit_local(local);
self.visit_local(local, context, location);
}
Lvalue::Static(ref $($mutability)* static_) => {
self.visit_static(static_, context, location);
Expand Down Expand Up @@ -662,8 +664,8 @@ macro_rules! make_mir_visitor {
ProjectionElem::Field(_field, ref $($mutability)* ty) => {
self.visit_ty(ty, Lookup::Loc(location));
}
ProjectionElem::Index(ref $($mutability)* operand) => {
self.visit_operand(operand, location);
ProjectionElem::Index(ref $($mutability)* local) => {
self.visit_local(local, LvalueContext::Consume, location);
}
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/structural_impls.rs
Expand Up @@ -421,7 +421,7 @@ macro_rules! CopyImpls {
}
}

CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId }
CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId, ::mir::Local }

impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {
Expand Down
29 changes: 6 additions & 23 deletions src/librustc_mir/borrow_check.rs
Expand Up @@ -212,11 +212,11 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
// ignored by borrowck
}

StatementKind::StorageDead(ref lvalue) => {
StatementKind::StorageDead(local) => {
// causes non-drop values to be dropped.
self.consume_lvalue(ContextKind::StorageDead.new(location),
ConsumeKind::Consume,
(lvalue, span),
(&Lvalue::Local(local), span),
flow_state)
}
}
Expand Down Expand Up @@ -710,7 +710,7 @@ mod restrictions {

use rustc::hir;
use rustc::ty::{self, TyCtxt};
use rustc::mir::{Lvalue, Mir, Operand, ProjectionElem};
use rustc::mir::{Lvalue, Mir, ProjectionElem};

pub(super) struct Restrictions<'c, 'tcx: 'c> {
mir: &'c Mir<'tcx>,
Expand Down Expand Up @@ -809,12 +809,7 @@ mod restrictions {
ProjectionElem::Downcast(..) |
ProjectionElem::Subslice { .. } |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Index(Operand::Constant(..)) => {
cursor = &proj.base;
continue 'cursor;
}
ProjectionElem::Index(Operand::Consume(ref index)) => {
self.lvalue_stack.push(index); // FIXME: did old borrowck do this?
ProjectionElem::Index(_) => {
cursor = &proj.base;
continue 'cursor;
}
Expand Down Expand Up @@ -1004,7 +999,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
("", format!(""), None), // (dont emit downcast info)
ProjectionElem::Field(field, _ty) =>
("", format!(".{}", field.index()), None),
ProjectionElem::Index(ref index) =>
ProjectionElem::Index(index) =>
("", format!(""), Some(index)),
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
("", format!("[{} of {}]", offset, min_length), None),
Expand All @@ -1021,23 +1016,11 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
self.append_lvalue_to_string(&proj.base, buf);
if let Some(index) = index_operand {
buf.push_str("[");
self.append_operand_to_string(index, buf);
self.append_lvalue_to_string(&Lvalue::Local(index), buf);
buf.push_str("]");
} else {
buf.push_str(&suffix);
}

}
}
}

fn append_operand_to_string(&self, operand: &Operand, buf: &mut String) {
match *operand {
Operand::Consume(ref lvalue) => {
self.append_lvalue_to_string(lvalue, buf);
}
Operand::Constant(ref constant) => {
buf.push_str(&format!("{:?}", constant));
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_mir/build/expr/as_lvalue.rs
Expand Up @@ -61,7 +61,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// region_scope=None so lvalue indexes live forever. They are scalars so they
// do not need storage annotations, and they are often copied between
// places.
let idx = unpack!(block = this.as_operand(block, None, index));
let idx = unpack!(block = this.as_temp(block, None, index));

// bounds check:
let (len, lt) = (this.temp(usize_ty.clone(), expr_span),
Expand All @@ -70,12 +70,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
&len, Rvalue::Len(slice.clone()));
this.cfg.push_assign(block, source_info, // lt = idx < len
&lt, Rvalue::BinaryOp(BinOp::Lt,
idx.clone(),
Operand::Consume(Lvalue::Local(idx)),
Operand::Consume(len.clone())));

let msg = AssertMessage::BoundsCheck {
len: Operand::Consume(len),
index: idx.clone()
index: Operand::Consume(Lvalue::Local(idx))
};
let success = this.assert(block, Operand::Consume(lt), true,
msg, expr_span);
Expand Down Expand Up @@ -127,7 +127,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Some(Category::Lvalue) => false,
_ => true,
});
this.as_temp(block, expr.temp_lifetime, expr)
let temp = unpack!(block = this.as_temp(block, expr.temp_lifetime, expr));
block.and(Lvalue::Local(temp))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/expr/as_operand.rs
Expand Up @@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Category::Rvalue(..) => {
let operand =
unpack!(block = this.as_temp(block, scope, expr));
block.and(Operand::Consume(operand))
block.and(Operand::Consume(Lvalue::Local(operand)))
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_mir/build/expr/as_rvalue.rs
Expand Up @@ -96,23 +96,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
ExprKind::Box { value } => {
let value = this.hir.mirror(value);
let result = this.temp(expr.ty, expr_span);
let result = this.local_decls.push(LocalDecl::new_temp(expr.ty, expr_span));
this.cfg.push(block, Statement {
source_info,
kind: StatementKind::StorageLive(result.clone())
kind: StatementKind::StorageLive(result)
});
if let Some(scope) = scope {
// schedule a shallow free of that memory, lest we unwind:
this.schedule_drop(expr_span, scope, &result, value.ty);
this.schedule_drop(expr_span, scope, &Lvalue::Local(result), value.ty);
}

// malloc some memory of suitable type (thus far, uninitialized):
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
this.cfg.push_assign(block, source_info, &result, box_);
this.cfg.push_assign(block, source_info, &Lvalue::Local(result), box_);

// initialize the box contents:
unpack!(block = this.into(&result.clone().deref(), block, value));
block.and(Rvalue::Use(Operand::Consume(result)))
unpack!(block = this.into(&Lvalue::Local(result).deref(), block, value));
block.and(Rvalue::Use(Operand::Consume(Lvalue::Local(result))))
}
ExprKind::Cast { source } => {
let source = this.hir.mirror(source);
Expand Down
16 changes: 8 additions & 8 deletions src/librustc_mir/build/expr/as_temp.rs
Expand Up @@ -23,7 +23,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
block: BasicBlock,
temp_lifetime: Option<region::Scope>,
expr: M)
-> BlockAnd<Lvalue<'tcx>>
-> BlockAnd<Local>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
let expr = self.hir.mirror(expr);
Expand All @@ -34,7 +34,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
mut block: BasicBlock,
temp_lifetime: Option<region::Scope>,
expr: Expr<'tcx>)
-> BlockAnd<Lvalue<'tcx>> {
-> BlockAnd<Local> {
debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})",
block, temp_lifetime, expr);
let this = self;
Expand All @@ -47,13 +47,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
});
}

let expr_ty = expr.ty.clone();
let temp = this.temp(expr_ty.clone(), expr_span);
let expr_ty = expr.ty;
let temp = this.local_decls.push(LocalDecl::new_temp(expr_ty, expr_span));

if !expr_ty.is_never() {
this.cfg.push(block, Statement {
source_info,
kind: StatementKind::StorageLive(temp.clone())
kind: StatementKind::StorageLive(temp)
});
}

Expand All @@ -68,18 +68,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Category::Lvalue => {
let lvalue = unpack!(block = this.as_lvalue(block, expr));
let rvalue = Rvalue::Use(Operand::Consume(lvalue));
this.cfg.push_assign(block, source_info, &temp, rvalue);
this.cfg.push_assign(block, source_info, &Lvalue::Local(temp), rvalue);
}
_ => {
unpack!(block = this.into(&temp, block, expr));
unpack!(block = this.into(&Lvalue::Local(temp), block, expr));
}
}

// In constants, temp_lifetime is None. We should not need to drop
// anything because no values with a destructor can be created in
// a constant at this time, even if the type may need dropping.
if let Some(temp_lifetime) = temp_lifetime {
this.schedule_drop(expr_span, temp_lifetime, &temp, expr_ty);
this.schedule_drop(expr_span, temp_lifetime, &Lvalue::Local(temp), expr_ty);
}

block.and(temp)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/expr/into.rs
Expand Up @@ -229,7 +229,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {

let topmost_scope = this.topmost_scope();
let ptr = unpack!(block = this.as_temp(block, Some(topmost_scope), ptr));
this.into(&ptr.deref(), block, val)
this.into(&Lvalue::Local(ptr).deref(), block, val)
} else {
let args: Vec<_> =
args.into_iter()
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/matches/mod.rs
Expand Up @@ -194,7 +194,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let source_info = self.source_info(span);
self.cfg.push(block, Statement {
source_info,
kind: StatementKind::StorageLive(Lvalue::Local(local_id))
kind: StatementKind::StorageLive(local_id)
});
Lvalue::Local(local_id)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/scope.rs
Expand Up @@ -822,7 +822,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
Lvalue::Local(index) if index.index() > arg_count => {
cfg.push(block, Statement {
source_info,
kind: StatementKind::StorageDead(drop_data.location.clone())
kind: StatementKind::StorageDead(index)
});
}
_ => continue
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_mir/dataflow/move_paths/abs_domain.rs
Expand Up @@ -21,8 +21,7 @@
//! `a[x]` would still overlap them both. But that is not this
//! representation does today.)

use rustc::mir::LvalueElem;
use rustc::mir::{Operand, ProjectionElem};
use rustc::mir::{Local, LvalueElem, Operand, ProjectionElem};
use rustc::ty::Ty;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
Expand All @@ -40,6 +39,10 @@ impl<'tcx> Lift for Operand<'tcx> {
type Abstract = AbstractOperand;
fn lift(&self) -> Self::Abstract { AbstractOperand }
}
impl Lift for Local {
type Abstract = AbstractOperand;
fn lift(&self) -> Self::Abstract { AbstractOperand }
}
impl<'tcx> Lift for Ty<'tcx> {
type Abstract = AbstractType;
fn lift(&self) -> Self::Abstract { AbstractType }
Expand Down

0 comments on commit 2f1ef9e

Please sign in to comment.