Auto merge of #30635 - nagisa:mir-rid-unit-temp, r=nikomatsakis

Get rid of that nasty unit_ty temporary variable created just because it might be handy to have one around, when in reality it isn’t really that useful at all.

r? @nikomatsakis

Fixes https://github.com/rust-lang/rust/issues/30637
This commit is contained in:
bors 2016-01-12 05:20:23 +00:00
commit d6cb2791ce
6 changed files with 56 additions and 46 deletions

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use build::{BlockAnd, Builder};
use build::{BlockAnd, BlockAndExtension, Builder};
use hair::*;
use rustc::mir::repr::*;
use rustc_front::hir;
@ -19,11 +19,16 @@ impl<'a,'tcx> Builder<'a,'tcx> {
mut block: BasicBlock,
ast_block: &'tcx hir::Block)
-> BlockAnd<()> {
let this = self;
let Block { extent, span: _, stmts, expr } = this.hir.mirror(ast_block);
this.in_scope(extent, block, |this| {
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
self.in_scope(extent, block, move |this| {
unpack!(block = this.stmts(block, stmts));
this.into(destination, block, expr)
match expr {
Some(expr) => this.into(destination, block, expr),
None => {
this.cfg.push_assign_unit(block, span, destination);
block.unit()
}
}
})
}
}

View File

@ -37,14 +37,6 @@ impl<'tcx> CFG<'tcx> {
self.block_data_mut(block).statements.push(statement);
}
pub fn push_assign_constant(&mut self,
block: BasicBlock,
span: Span,
temp: &Lvalue<'tcx>,
constant: Constant<'tcx>) {
self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant)));
}
pub fn push_drop(&mut self, block: BasicBlock, span: Span,
kind: DropKind, lvalue: &Lvalue<'tcx>) {
self.push(block, Statement {
@ -64,6 +56,23 @@ impl<'tcx> CFG<'tcx> {
});
}
pub fn push_assign_constant(&mut self,
block: BasicBlock,
span: Span,
temp: &Lvalue<'tcx>,
constant: Constant<'tcx>) {
self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant)));
}
pub fn push_assign_unit(&mut self,
block: BasicBlock,
span: Span,
lvalue: &Lvalue<'tcx>) {
self.push_assign(block, span, lvalue, Rvalue::Aggregate(
AggregateKind::Tuple, vec![]
));
}
pub fn terminate(&mut self,
block: BasicBlock,
terminator: Terminator<'tcx>) {

View File

@ -58,7 +58,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
});
unpack!(then_block = this.into(destination, then_block, then_expr));
unpack!(else_block = this.into(destination, else_block, else_expr));
else_block = if let Some(else_expr) = else_expr {
unpack!(this.into(destination, else_block, else_expr))
} else {
// Body of the `if` expression without an `else` clause must return `()`, thus
// we implicitly generate a `else {}` if it is not specified.
this.cfg.push_assign_unit(else_block, expr_span, &Lvalue::ReturnPointer);
else_block
};
let join_block = this.cfg.start_new_block();
this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
@ -157,11 +164,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
}
// execute the body, branching back to the test
let unit_temp = this.unit_temp.clone();
let body_block_end = unpack!(this.into(&unit_temp, body_block, body));
// We write bodys “return value” into the destination of loop. This is fine,
// because:
//
// * In Rust both loop expression and its body are required to have `()`
// as the “return value”;
// * The destination will be considered uninitialised (given it was
// uninitialised before the loop) during the first iteration, thus
// disallowing its use inside the body. Alternatively, if it was already
// initialised, the `destination` can only possibly have a value of `()`,
// therefore, “mutating” the destination during iteration is fine.
let body_block_end = unpack!(this.into(destination, body_block, body));
this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
// final point is exit_block
exit_block.unit()
})
}
@ -206,7 +220,13 @@ impl<'a,'tcx> Builder<'a,'tcx> {
this.break_or_continue(expr_span, label, block, |loop_scope| loop_scope.break_block)
}
ExprKind::Return { value } => {
unpack!(block = this.into(&Lvalue::ReturnPointer, block, value));
block = match value {
Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
None => {
this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
block
}
};
let extent = this.extent_of_outermost_scope();
this.exit_scope(expr_span, extent, block, END_BLOCK);
this.cfg.start_new_block().unit()

View File

@ -14,7 +14,7 @@
//! wrapped up as expressions (e.g. blocks). To make this ergonomic, we use this
//! latter `EvalInto` trait.
use build::{BlockAnd, BlockAndExtension, Builder};
use build::{BlockAnd, Builder};
use hair::*;
use rustc::mir::repr::*;
@ -58,16 +58,3 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
builder.into_expr(destination, block, self)
}
}
impl<'tcx> EvalInto<'tcx> for Option<ExprRef<'tcx>> {
fn eval_into<'a>(self,
builder: &mut Builder<'a, 'tcx>,
destination: &Lvalue<'tcx>,
block: BasicBlock)
-> BlockAnd<()> {
match self {
Some(expr) => builder.into(destination, block, expr),
None => block.unit(),
}
}
}

View File

@ -23,7 +23,6 @@ pub struct Builder<'a, 'tcx: 'a> {
cfg: CFG<'tcx>,
scopes: Vec<scope::Scope<'tcx>>,
loop_scopes: Vec<scope::LoopScope>,
unit_temp: Lvalue<'tcx>,
var_decls: Vec<VarDecl<'tcx>>,
var_indices: FnvHashMap<ast::NodeId, u32>,
temp_decls: Vec<TempDecl<'tcx>>,
@ -79,7 +78,7 @@ macro_rules! unpack {
///////////////////////////////////////////////////////////////////////////
// construct() -- the main entry point for building MIR for a function
pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
_span: Span,
implicit_arguments: Vec<Ty<'tcx>>,
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
@ -89,20 +88,14 @@ pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
-> Mir<'tcx> {
let cfg = CFG { basic_blocks: vec![] };
// it's handy to have a temporary of type `()` sometimes, so make
// one from the start and keep it available
let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
let unit_temp = Lvalue::Temp(0);
let mut builder = Builder {
hir: hir,
cfg: cfg,
scopes: vec![],
loop_scopes: vec![],
temp_decls: temp_decls,
temp_decls: vec![],
var_decls: vec![],
var_indices: FnvHashMap(),
unit_temp: unit_temp,
};
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);

View File

@ -46,10 +46,6 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
ast.make_mirror(self)
}
pub fn unit_ty(&mut self) -> Ty<'tcx> {
self.tcx.mk_nil()
}
pub fn usize_ty(&mut self) -> Ty<'tcx> {
self.tcx.types.usize
}