mir: place match pattern bindings in their respective arms.
This commit is contained in:
parent
f06bab7758
commit
e2ac9895d6
2 changed files with 24 additions and 18 deletions
|
@ -37,25 +37,28 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
-> BlockAnd<()> {
|
-> BlockAnd<()> {
|
||||||
let discriminant_lvalue = unpack!(block = self.as_lvalue(block, discriminant));
|
let discriminant_lvalue = unpack!(block = self.as_lvalue(block, discriminant));
|
||||||
|
|
||||||
// Before we do anything, create uninitialized variables with
|
|
||||||
// suitable extent for all of the bindings in this match. It's
|
|
||||||
// easiest to do this up front because some of these arms may
|
|
||||||
// be unreachable or reachable multiple times.
|
|
||||||
let var_scope_id = self.innermost_scope_id();
|
|
||||||
for arm in &arms {
|
|
||||||
self.declare_bindings(var_scope_id, &arm.patterns[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut arm_blocks = ArmBlocks {
|
let mut arm_blocks = ArmBlocks {
|
||||||
blocks: arms.iter()
|
blocks: arms.iter()
|
||||||
.map(|_| self.cfg.start_new_block())
|
.map(|_| self.cfg.start_new_block())
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let arm_bodies: Vec<ExprRef<'tcx>> =
|
// Get the body expressions and their scopes, while declaring bindings.
|
||||||
arms.iter()
|
let arm_bodies: Vec<_> = arms.iter().enumerate().map(|(i, arm)| {
|
||||||
.map(|arm| arm.body.clone())
|
// Assume that all expressions are wrapped in Scope.
|
||||||
.collect();
|
let body = self.hir.mirror(arm.body.clone());
|
||||||
|
match body.kind {
|
||||||
|
ExprKind::Scope { extent, value } => {
|
||||||
|
let scope_id = self.push_scope(extent, arm_blocks.blocks[i]);
|
||||||
|
self.declare_bindings(scope_id, &arm.patterns[0]);
|
||||||
|
(extent, self.scopes.pop().unwrap(), value)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
span_bug!(body.span, "arm body is not wrapped in Scope {:?}",
|
||||||
|
body.kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
// assemble a list of candidates: there is one candidate per
|
// assemble a list of candidates: there is one candidate per
|
||||||
// pattern, which means there may be more than one candidate
|
// pattern, which means there may be more than one candidate
|
||||||
|
@ -95,11 +98,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
// all the arm blocks will rejoin here
|
// all the arm blocks will rejoin here
|
||||||
let end_block = self.cfg.start_new_block();
|
let end_block = self.cfg.start_new_block();
|
||||||
|
|
||||||
for (arm_index, arm_body) in arm_bodies.into_iter().enumerate() {
|
let scope_id = self.innermost_scope_id();
|
||||||
|
for (arm_index, (extent, scope, body)) in arm_bodies.into_iter().enumerate() {
|
||||||
let mut arm_block = arm_blocks.blocks[arm_index];
|
let mut arm_block = arm_blocks.blocks[arm_index];
|
||||||
unpack!(arm_block = self.into(destination, arm_block, arm_body));
|
// Re-enter the scope we created the bindings in.
|
||||||
|
self.scopes.push(scope);
|
||||||
|
unpack!(arm_block = self.into(destination, arm_block, body));
|
||||||
|
unpack!(arm_block = self.pop_scope(extent, arm_block));
|
||||||
self.cfg.terminate(arm_block,
|
self.cfg.terminate(arm_block,
|
||||||
var_scope_id,
|
scope_id,
|
||||||
span,
|
span,
|
||||||
TerminatorKind::Goto { target: end_block });
|
TerminatorKind::Goto { target: end_block });
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![feature(omit_gdb_pretty_printer_section, rustc_attrs)]
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
trait TraitWithAssocType {
|
trait TraitWithAssocType {
|
||||||
|
@ -127,7 +127,6 @@ fn assoc_tuple<T: TraitWithAssocType>(arg: (T, T::Type)) {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME(#32790) MIR reuses scopes for match arms.
|
|
||||||
fn assoc_enum<T: TraitWithAssocType>(arg: Enum<T>) {
|
fn assoc_enum<T: TraitWithAssocType>(arg: Enum<T>) {
|
||||||
|
|
||||||
match arg {
|
match arg {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue