Skip to content

Commit d6cb279

Browse files
committed
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 #30637
2 parents dedaebd + 3692ab6 commit d6cb279

File tree

6 files changed

+56
-46
lines changed

6 files changed

+56
-46
lines changed

src/librustc_mir/build/block.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use build::{BlockAnd, Builder};
11+
use build::{BlockAnd, BlockAndExtension, Builder};
1212
use hair::*;
1313
use rustc::mir::repr::*;
1414
use rustc_front::hir;
@@ -19,11 +19,16 @@ impl<'a,'tcx> Builder<'a,'tcx> {
1919
mut block: BasicBlock,
2020
ast_block: &'tcx hir::Block)
2121
-> BlockAnd<()> {
22-
let this = self;
23-
let Block { extent, span: _, stmts, expr } = this.hir.mirror(ast_block);
24-
this.in_scope(extent, block, |this| {
22+
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
23+
self.in_scope(extent, block, move |this| {
2524
unpack!(block = this.stmts(block, stmts));
26-
this.into(destination, block, expr)
25+
match expr {
26+
Some(expr) => this.into(destination, block, expr),
27+
None => {
28+
this.cfg.push_assign_unit(block, span, destination);
29+
block.unit()
30+
}
31+
}
2732
})
2833
}
2934
}

src/librustc_mir/build/cfg.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ impl<'tcx> CFG<'tcx> {
3737
self.block_data_mut(block).statements.push(statement);
3838
}
3939

40-
pub fn push_assign_constant(&mut self,
41-
block: BasicBlock,
42-
span: Span,
43-
temp: &Lvalue<'tcx>,
44-
constant: Constant<'tcx>) {
45-
self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant)));
46-
}
47-
4840
pub fn push_drop(&mut self, block: BasicBlock, span: Span,
4941
kind: DropKind, lvalue: &Lvalue<'tcx>) {
5042
self.push(block, Statement {
@@ -64,6 +56,23 @@ impl<'tcx> CFG<'tcx> {
6456
});
6557
}
6658

59+
pub fn push_assign_constant(&mut self,
60+
block: BasicBlock,
61+
span: Span,
62+
temp: &Lvalue<'tcx>,
63+
constant: Constant<'tcx>) {
64+
self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant)));
65+
}
66+
67+
pub fn push_assign_unit(&mut self,
68+
block: BasicBlock,
69+
span: Span,
70+
lvalue: &Lvalue<'tcx>) {
71+
self.push_assign(block, span, lvalue, Rvalue::Aggregate(
72+
AggregateKind::Tuple, vec![]
73+
));
74+
}
75+
6776
pub fn terminate(&mut self,
6877
block: BasicBlock,
6978
terminator: Terminator<'tcx>) {

src/librustc_mir/build/expr/into.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
5858
});
5959

6060
unpack!(then_block = this.into(destination, then_block, then_expr));
61-
unpack!(else_block = this.into(destination, else_block, else_expr));
61+
else_block = if let Some(else_expr) = else_expr {
62+
unpack!(this.into(destination, else_block, else_expr))
63+
} else {
64+
// Body of the `if` expression without an `else` clause must return `()`, thus
65+
// we implicitly generate a `else {}` if it is not specified.
66+
this.cfg.push_assign_unit(else_block, expr_span, &Lvalue::ReturnPointer);
67+
else_block
68+
};
6269

6370
let join_block = this.cfg.start_new_block();
6471
this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
@@ -157,11 +164,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
157164
}
158165

159166
// execute the body, branching back to the test
160-
let unit_temp = this.unit_temp.clone();
161-
let body_block_end = unpack!(this.into(&unit_temp, body_block, body));
167+
// We write body’s “return value” into the destination of loop. This is fine,
168+
// because:
169+
//
170+
// * In Rust both loop expression and its body are required to have `()`
171+
// as the “return value”;
172+
// * The destination will be considered uninitialised (given it was
173+
// uninitialised before the loop) during the first iteration, thus
174+
// disallowing its use inside the body. Alternatively, if it was already
175+
// initialised, the `destination` can only possibly have a value of `()`,
176+
// therefore, “mutating” the destination during iteration is fine.
177+
let body_block_end = unpack!(this.into(destination, body_block, body));
162178
this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
163-
164-
// final point is exit_block
165179
exit_block.unit()
166180
})
167181
}
@@ -206,7 +220,13 @@ impl<'a,'tcx> Builder<'a,'tcx> {
206220
this.break_or_continue(expr_span, label, block, |loop_scope| loop_scope.break_block)
207221
}
208222
ExprKind::Return { value } => {
209-
unpack!(block = this.into(&Lvalue::ReturnPointer, block, value));
223+
block = match value {
224+
Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
225+
None => {
226+
this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
227+
block
228+
}
229+
};
210230
let extent = this.extent_of_outermost_scope();
211231
this.exit_scope(expr_span, extent, block, END_BLOCK);
212232
this.cfg.start_new_block().unit()

src/librustc_mir/build/into.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! wrapped up as expressions (e.g. blocks). To make this ergonomic, we use this
1515
//! latter `EvalInto` trait.
1616
17-
use build::{BlockAnd, BlockAndExtension, Builder};
17+
use build::{BlockAnd, Builder};
1818
use hair::*;
1919
use rustc::mir::repr::*;
2020

@@ -58,16 +58,3 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
5858
builder.into_expr(destination, block, self)
5959
}
6060
}
61-
62-
impl<'tcx> EvalInto<'tcx> for Option<ExprRef<'tcx>> {
63-
fn eval_into<'a>(self,
64-
builder: &mut Builder<'a, 'tcx>,
65-
destination: &Lvalue<'tcx>,
66-
block: BasicBlock)
67-
-> BlockAnd<()> {
68-
match self {
69-
Some(expr) => builder.into(destination, block, expr),
70-
None => block.unit(),
71-
}
72-
}
73-
}

src/librustc_mir/build/mod.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ pub struct Builder<'a, 'tcx: 'a> {
2323
cfg: CFG<'tcx>,
2424
scopes: Vec<scope::Scope<'tcx>>,
2525
loop_scopes: Vec<scope::LoopScope>,
26-
unit_temp: Lvalue<'tcx>,
2726
var_decls: Vec<VarDecl<'tcx>>,
2827
var_indices: FnvHashMap<ast::NodeId, u32>,
2928
temp_decls: Vec<TempDecl<'tcx>>,
@@ -79,7 +78,7 @@ macro_rules! unpack {
7978
///////////////////////////////////////////////////////////////////////////
8079
// construct() -- the main entry point for building MIR for a function
8180

82-
pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
81+
pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
8382
_span: Span,
8483
implicit_arguments: Vec<Ty<'tcx>>,
8584
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
@@ -89,20 +88,14 @@ pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
8988
-> Mir<'tcx> {
9089
let cfg = CFG { basic_blocks: vec![] };
9190

92-
// it's handy to have a temporary of type `()` sometimes, so make
93-
// one from the start and keep it available
94-
let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
95-
let unit_temp = Lvalue::Temp(0);
96-
9791
let mut builder = Builder {
9892
hir: hir,
9993
cfg: cfg,
10094
scopes: vec![],
10195
loop_scopes: vec![],
102-
temp_decls: temp_decls,
96+
temp_decls: vec![],
10397
var_decls: vec![],
10498
var_indices: FnvHashMap(),
105-
unit_temp: unit_temp,
10699
};
107100

108101
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);

src/librustc_mir/hair/cx/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
4646
ast.make_mirror(self)
4747
}
4848

49-
pub fn unit_ty(&mut self) -> Ty<'tcx> {
50-
self.tcx.mk_nil()
51-
}
52-
5349
pub fn usize_ty(&mut self) -> Ty<'tcx> {
5450
self.tcx.types.usize
5551
}

0 commit comments

Comments
 (0)