Skip to content

Commit 77be4ec

Browse files
committed
Make list of statements flat
In MIR we previously tried to match `let x in { exprs; let y in { exprs; }}` with our data structures which is rather unwieldy, espeicially because it requires some sort of recursion or stack to process, while, a flat list of statements is enough – lets only relinquish their lifetime at the end of the block (i.e. end of the list). Also fixes #31853.
1 parent fbd8171 commit 77be4ec

File tree

7 files changed

+73
-110
lines changed

7 files changed

+73
-110
lines changed

src/librustc/dep_graph/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &ty::ctxt<'tcx>,
198198
fn visit_item(&mut self, i: &'tcx hir::Item) {
199199
let item_def_id = self.tcx.map.local_def_id(i.id);
200200
let task_id = (self.dep_node_fn)(item_def_id);
201-
debug!("About to start task {:?}", task_id);
202201
let _task = self.tcx.dep_graph.in_task(task_id);
202+
debug!("Started task {:?}", task_id);
203203
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
204204
self.visitor.visit_item(i)
205205
}

src/librustc_mir/build/block.rs

+62-6
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,70 @@ impl<'a,'tcx> Builder<'a,'tcx> {
2121
-> BlockAnd<()> {
2222
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
2323
self.in_scope(extent, block, move |this| {
24-
unpack!(block = this.stmts(block, stmts));
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()
24+
// This convoluted structure is to avoid using recursion as we walk down a list
25+
// of statements. Basically, the structure we get back is something like:
26+
//
27+
// let x = <init> in {
28+
// expr1;
29+
// let y = <init> in {
30+
// expr2;
31+
// expr3;
32+
// ...
33+
// }
34+
// }
35+
//
36+
// The let bindings are valid till the end of block so all we have to do is to pop all
37+
// the let-scopes at the end.
38+
//
39+
// First we build all the statements in the block.
40+
let mut let_extent_stack = Vec::with_capacity(8);
41+
for stmt in stmts {
42+
let Stmt { span: _, kind } = this.hir.mirror(stmt);
43+
match kind {
44+
StmtKind::Expr { scope, expr } => {
45+
unpack!(block = this.in_scope(scope, block, |this| {
46+
let expr = this.hir.mirror(expr);
47+
let temp = this.temp(expr.ty.clone());
48+
unpack!(block = this.into(&temp, block, expr));
49+
unpack!(block = this.build_drop(block, temp));
50+
block.unit()
51+
}));
52+
}
53+
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
54+
this.push_scope(remainder_scope);
55+
let_extent_stack.push(remainder_scope);
56+
unpack!(block = this.in_scope(init_scope, block, move |this| {
57+
// FIXME #30046 ^~~~
58+
match initializer {
59+
Some(initializer) => {
60+
this.expr_into_pattern(block,
61+
remainder_scope,
62+
pattern,
63+
initializer)
64+
}
65+
None => {
66+
this.declare_bindings(remainder_scope, &pattern);
67+
block.unit()
68+
}
69+
}
70+
}));
71+
}
3072
}
3173
}
74+
// Then, the block may have an optional trailing expression which is a “return” value
75+
// of the block.
76+
if let Some(expr) = expr {
77+
unpack!(block = this.into(destination, block, expr));
78+
} else {
79+
// FIXME(#31472)
80+
this.cfg.push_assign_unit(block, span, destination);
81+
}
82+
// Finally, we pop all the let scopes before exiting out from the scope of block
83+
// itself.
84+
for extent in let_extent_stack.into_iter().rev() {
85+
unpack!(block = this.pop_scope(extent, block));
86+
}
87+
block.unit()
3288
})
3389
}
3490
}

src/librustc_mir/build/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,3 @@ mod into;
185185
mod matches;
186186
mod misc;
187187
mod scope;
188-
mod stmt;

src/librustc_mir/build/scope.rs

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
249249
extent: CodeExtent,
250250
mut block: BasicBlock,
251251
target: BasicBlock) {
252+
debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
252253
let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent)
253254
.unwrap_or_else(||{
254255
self.hir.span_bug(span, &format!("extent {:?} does not enclose", extent))

src/librustc_mir/build/stmt.rs

-83
This file was deleted.

src/librustc_mir/hair/cx/block.rs

+8-15
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
2626
extent: cx.tcx.region_maps.node_extent(self.id),
2727
span: self.span,
2828
stmts: stmts,
29-
expr: self.expr.to_ref(),
29+
expr: self.expr.to_ref()
3030
}
3131
}
3232
}
@@ -41,13 +41,13 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
4141
while let Some((index, stmt)) = stmts.next() {
4242
match stmt.node {
4343
hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) =>
44-
result.push(
45-
StmtRef::Mirror(
46-
Box::new(Stmt { span: stmt.span,
47-
kind: StmtKind::Expr {
48-
scope: cx.tcx.region_maps.node_extent(id),
49-
expr: expr.to_ref() } }))),
50-
44+
result.push(StmtRef::Mirror(Box::new(Stmt {
45+
span: stmt.span,
46+
kind: StmtKind::Expr {
47+
scope: cx.tcx.region_maps.node_extent(id),
48+
expr: expr.to_ref()
49+
}
50+
}))),
5151
hir::StmtDecl(ref decl, id) => {
5252
match decl.node {
5353
hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
@@ -59,10 +59,6 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
5959
let remainder_extent =
6060
cx.tcx.region_maps.lookup_code_extent(remainder_extent);
6161

62-
// pull in all following statements, since
63-
// they are within the scope of this let:
64-
let following_stmts = mirror_stmts(cx, block_id, stmts);
65-
6662
let pattern = cx.irrefutable_pat(&local.pat);
6763
result.push(StmtRef::Mirror(Box::new(Stmt {
6864
span: stmt.span,
@@ -71,11 +67,8 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
7167
init_scope: cx.tcx.region_maps.node_extent(id),
7268
pattern: pattern,
7369
initializer: local.init.to_ref(),
74-
stmts: following_stmts,
7570
},
7671
})));
77-
78-
return result;
7972
}
8073
}
8174
}

src/librustc_mir/hair/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,7 @@ pub enum StmtKind<'tcx> {
7878
pattern: Pattern<'tcx>,
7979

8080
/// let pat = <INIT> ...
81-
initializer: Option<ExprRef<'tcx>>,
82-
83-
/// let pat = init; <STMTS>
84-
stmts: Vec<StmtRef<'tcx>>,
81+
initializer: Option<ExprRef<'tcx>>
8582
},
8683
}
8784

0 commit comments

Comments
 (0)