Skip to content

Commit 96a3cd0

Browse files
committed
rather than just passing the block around, track the candidate's index,
and track which arms are reached (though in fact we don't make use of this right now -- we might later if we absorb the checking of patterns into MIR, as I would like)
1 parent 1f4acfa commit 96a3cd0

File tree

1 file changed

+31
-19
lines changed
  • src/librustc_mir/build/matches

1 file changed

+31
-19
lines changed

src/librustc_mir/build/matches/mod.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ impl<H:Hair> Builder<H> {
3434
let discriminant_lvalue =
3535
unpack!(block = self.as_lvalue(block, discriminant));
3636

37-
let arm_blocks: Vec<BasicBlock> =
38-
arms.iter()
39-
.map(|_| self.cfg.start_new_block())
40-
.collect();
37+
let mut arm_blocks = ArmBlocks {
38+
blocks: arms.iter()
39+
.map(|_| self.cfg.start_new_block())
40+
.collect(),
41+
};
4142

4243
let arm_bodies: Vec<ExprRef<H>> =
4344
arms.iter()
@@ -52,34 +53,34 @@ impl<H:Hair> Builder<H> {
5253
// source.
5354
let candidates: Vec<Candidate<H>> =
5455
arms.into_iter()
55-
.zip(arm_blocks.iter())
56+
.enumerate()
5657
.rev() // highest priority comes last
57-
.flat_map(|(arm, &arm_block)| {
58+
.flat_map(|(arm_index, arm)| {
5859
let guard = arm.guard;
5960
arm.patterns.into_iter()
6061
.rev()
61-
.map(move |pat| (arm_block, pat, guard.clone()))
62+
.map(move |pat| (arm_index, pat, guard.clone()))
6263
})
63-
.map(|(arm_block, pattern, guard)| {
64+
.map(|(arm_index, pattern, guard)| {
6465
Candidate {
6566
match_pairs: vec![self.match_pair(discriminant_lvalue.clone(), pattern)],
6667
bindings: vec![],
6768
guard: guard,
68-
arm_block: arm_block,
69+
arm_index: arm_index,
6970
}
7071
})
7172
.collect();
7273

7374
// this will generate code to test discriminant_lvalue and
7475
// branch to the appropriate arm block
7576
let var_extent = self.extent_of_innermost_scope().unwrap();
76-
self.match_candidates(span, var_extent, candidates, block);
77+
self.match_candidates(span, var_extent, &mut arm_blocks, candidates, block);
7778

7879
// all the arm blocks will rejoin here
7980
let end_block = self.cfg.start_new_block();
8081

81-
for (arm_body, &arm_block) in arm_bodies.into_iter().zip(arm_blocks.iter()) {
82-
let mut arm_block = arm_block;
82+
for (arm_index, arm_body) in arm_bodies.into_iter().enumerate() {
83+
let mut arm_block = arm_blocks.blocks[arm_index];
8384
unpack!(arm_block = self.into(destination, arm_block, arm_body));
8485
self.cfg.terminate(arm_block, Terminator::Goto { target: end_block });
8586
}
@@ -127,7 +128,7 @@ impl<H:Hair> Builder<H> {
127128
match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat)],
128129
bindings: vec![],
129130
guard: None,
130-
arm_block: block
131+
arm_index: 0, // since we don't call `match_candidates`, this field is unused
131132
};
132133

133134
// Simplify the candidate. Since the pattern is irrefutable, this should
@@ -180,6 +181,12 @@ impl<H:Hair> Builder<H> {
180181
}
181182
}
182183

184+
/// List of blocks for each arm (and potentially other metadata in the
185+
/// future).
186+
struct ArmBlocks {
187+
blocks: Vec<BasicBlock>,
188+
}
189+
183190
#[derive(Clone, Debug)]
184191
struct Candidate<H:Hair> {
185192
// all of these must be satisfied...
@@ -191,8 +198,8 @@ struct Candidate<H:Hair> {
191198
// ...and the guard must be evaluated...
192199
guard: Option<ExprRef<H>>,
193200

194-
// ...and then we branch here.
195-
arm_block: BasicBlock,
201+
// ...and then we branch to arm with this index.
202+
arm_index: usize,
196203
}
197204

198205
#[derive(Clone, Debug)]
@@ -243,6 +250,7 @@ impl<H:Hair> Builder<H> {
243250
fn match_candidates(&mut self,
244251
span: H::Span,
245252
var_extent: H::CodeExtent,
253+
arm_blocks: &mut ArmBlocks,
246254
mut candidates: Vec<Candidate<H>>,
247255
mut block: BasicBlock)
248256
{
@@ -267,7 +275,8 @@ impl<H:Hair> Builder<H> {
267275
// If so, apply any bindings, test the guard (if any), and
268276
// branch to the arm.
269277
let candidate = candidates.pop().unwrap();
270-
if let Some(b) = self.bind_and_guard_matched_candidate(block, var_extent, candidate) {
278+
if let Some(b) = self.bind_and_guard_matched_candidate(block, var_extent,
279+
arm_blocks, candidate) {
271280
block = b;
272281
} else {
273282
// if None is returned, then any remaining candidates
@@ -300,7 +309,7 @@ impl<H:Hair> Builder<H> {
300309
candidate))
301310
})
302311
.collect();
303-
self.match_candidates(span, var_extent, applicable_candidates, target_block);
312+
self.match_candidates(span, var_extent, arm_blocks, applicable_candidates, target_block);
304313
}
305314
}
306315

@@ -319,6 +328,7 @@ impl<H:Hair> Builder<H> {
319328
fn bind_and_guard_matched_candidate(&mut self,
320329
mut block: BasicBlock,
321330
var_extent: H::CodeExtent,
331+
arm_blocks: &mut ArmBlocks,
322332
candidate: Candidate<H>)
323333
-> Option<BasicBlock> {
324334
debug!("bind_and_guard_matched_candidate(block={:?}, var_extent={:?}, candidate={:?})",
@@ -328,16 +338,18 @@ impl<H:Hair> Builder<H> {
328338

329339
self.bind_matched_candidate(block, var_extent, candidate.bindings);
330340

341+
let arm_block = arm_blocks.blocks[candidate.arm_index];
342+
331343
if let Some(guard) = candidate.guard {
332344
// the block to branch to if the guard fails; if there is no
333345
// guard, this block is simply unreachable
334346
let cond = unpack!(block = self.as_operand(block, guard));
335347
let otherwise = self.cfg.start_new_block();
336348
self.cfg.terminate(block, Terminator::If { cond: cond,
337-
targets: [candidate.arm_block, otherwise]});
349+
targets: [arm_block, otherwise]});
338350
Some(otherwise)
339351
} else {
340-
self.cfg.terminate(block, Terminator::Goto { target: candidate.arm_block });
352+
self.cfg.terminate(block, Terminator::Goto { target: arm_block });
341353
None
342354
}
343355
}

0 commit comments

Comments
 (0)