Skip to content

Commit c1b3b7e

Browse files
committed
---
yaml --- r: 82560 b: refs/heads/auto c: 16e87cb h: refs/heads/master v: v3
1 parent 3d498c3 commit c1b3b7e

File tree

2 files changed

+77
-27
lines changed

2 files changed

+77
-27
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: 15ce791ff5b5756b1455c65708782bc8028de56f
16+
refs/heads/auto: 16e87cb5279cd85ac11eb31de8a0087b08d831eb
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/librustc/middle/trans/_match.rs

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ fn enter_default<'r>(bcx: @mut Block,
533533
m: &[Match<'r>],
534534
col: uint,
535535
val: ValueRef,
536-
chk: Option<mk_fail>)
536+
chk: FailureHandler)
537537
-> ~[Match<'r>] {
538538
debug!("enter_default(bcx=%s, m=%s, col=%u, val=%s)",
539539
bcx.to_str(),
@@ -567,7 +567,7 @@ fn enter_default<'r>(bcx: @mut Block,
567567
// we don't need any default cases. If the check *isn't* nonexhaustive
568568
// (because chk is Some), then we need the defaults anyways.
569569
let is_exhaustive = match matches.last_opt() {
570-
Some(m) if m.data.arm.guard.is_some() && chk.is_none() => true,
570+
Some(m) if m.data.arm.guard.is_some() && chk.is_infallible() => true,
571571
_ => false
572572
};
573573

@@ -1185,7 +1185,62 @@ fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
11851185
}
11861186
}
11871187

1188-
type mk_fail = @fn() -> BasicBlockRef;
1188+
trait CustomFailureHandler {
1189+
fn handle_fail(&self) -> BasicBlockRef;
1190+
}
1191+
1192+
struct DynamicFailureHandler {
1193+
bcx: @mut Block,
1194+
sp: span,
1195+
msg: @str,
1196+
finished: @mut Option<BasicBlockRef>,
1197+
}
1198+
1199+
impl CustomFailureHandler for DynamicFailureHandler {
1200+
fn handle_fail(&self) -> BasicBlockRef {
1201+
match *self.finished {
1202+
Some(bb) => return bb,
1203+
_ => (),
1204+
}
1205+
1206+
let fail_cx = sub_block(self.bcx, "case_fallthrough");
1207+
controlflow::trans_fail(fail_cx, Some(self.sp), self.msg);
1208+
*self.finished = Some(fail_cx.llbb);
1209+
fail_cx.llbb
1210+
}
1211+
}
1212+
1213+
/// What to do when the pattern match fails.
1214+
enum FailureHandler {
1215+
Infallible,
1216+
JumpToBasicBlock(BasicBlockRef),
1217+
CustomFailureHandlerClass(@CustomFailureHandler),
1218+
}
1219+
1220+
impl FailureHandler {
1221+
fn is_infallible(&self) -> bool {
1222+
match *self {
1223+
Infallible => true,
1224+
_ => false,
1225+
}
1226+
}
1227+
1228+
fn is_fallible(&self) -> bool {
1229+
!self.is_infallible()
1230+
}
1231+
1232+
fn handle_fail(&self) -> BasicBlockRef {
1233+
match *self {
1234+
Infallible => {
1235+
fail!("attempted to fail in infallible failure handler!")
1236+
}
1237+
JumpToBasicBlock(basic_block) => basic_block,
1238+
CustomFailureHandlerClass(custom_failure_handler) => {
1239+
custom_failure_handler.handle_fail()
1240+
}
1241+
}
1242+
}
1243+
}
11891244

11901245
fn pick_col(m: &[Match]) -> uint {
11911246
fn score(p: &ast::Pat) -> uint {
@@ -1347,7 +1402,7 @@ fn compile_guard(bcx: @mut Block,
13471402
data: &ArmData,
13481403
m: &[Match],
13491404
vals: &[ValueRef],
1350-
chk: Option<mk_fail>)
1405+
chk: FailureHandler)
13511406
-> @mut Block {
13521407
debug!("compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%s)",
13531408
bcx.to_str(),
@@ -1400,9 +1455,9 @@ fn compile_guard(bcx: @mut Block,
14001455
}
14011456

14021457
fn compile_submatch(bcx: @mut Block,
1403-
m: &[Match],
1404-
vals: &[ValueRef],
1405-
chk: Option<mk_fail>) {
1458+
m: &[Match],
1459+
vals: &[ValueRef],
1460+
chk: FailureHandler) {
14061461
debug!("compile_submatch(bcx=%s, m=%s, vals=%s)",
14071462
bcx.to_str(),
14081463
m.repr(bcx.tcx()),
@@ -1412,11 +1467,11 @@ fn compile_submatch(bcx: @mut Block,
14121467
/*
14131468
For an empty match, a fall-through case must exist
14141469
*/
1415-
assert!((m.len() > 0u || chk.is_some()));
1470+
assert!((m.len() > 0u || chk.is_fallible()));
14161471
let _icx = push_ctxt("match::compile_submatch");
14171472
let mut bcx = bcx;
14181473
if m.len() == 0u {
1419-
Br(bcx, chk.unwrap()());
1474+
Br(bcx, chk.handle_fail());
14201475
return;
14211476
}
14221477
if m[0].pats.len() == 0u {
@@ -1454,7 +1509,7 @@ fn compile_submatch(bcx: @mut Block,
14541509
fn compile_submatch_continue(mut bcx: @mut Block,
14551510
m: &[Match],
14561511
vals: &[ValueRef],
1457-
chk: Option<mk_fail>,
1512+
chk: FailureHandler,
14581513
col: uint,
14591514
val: ValueRef) {
14601515
let tcx = bcx.tcx();
@@ -1617,7 +1672,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
16171672
};
16181673

16191674
let defaults = enter_default(else_cx, dm, m, col, val, chk);
1620-
let exhaustive = chk.is_none() && defaults.len() == 0u;
1675+
let exhaustive = chk.is_infallible() && defaults.len() == 0u;
16211676
let len = opts.len();
16221677

16231678
// Compile subtrees for each option
@@ -1721,7 +1776,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
17211776

17221777
// If none of these subcases match, move on to the
17231778
// next condition.
1724-
branch_chk = Some::<mk_fail>(|| bcx.llbb);
1779+
branch_chk = JumpToBasicBlock(bcx.llbb);
17251780
CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
17261781
}
17271782
_ => ()
@@ -1860,11 +1915,15 @@ fn trans_match_inner(scope_cx: @mut Block,
18601915
if ty::type_is_empty(tcx, t) {
18611916
// Special case for empty types
18621917
let fail_cx = @mut None;
1863-
let f: mk_fail = || mk_fail(scope_cx, discr_expr.span,
1864-
@"scrutinizing value that can't exist", fail_cx);
1865-
Some(f)
1918+
let fail_handler = @DynamicFailureHandler {
1919+
bcx: scope_cx,
1920+
sp: discr_expr.span,
1921+
msg: @"scrutinizing value that can't exist",
1922+
finished: fail_cx,
1923+
} as @CustomFailureHandler;
1924+
CustomFailureHandlerClass(fail_handler)
18661925
} else {
1867-
None
1926+
Infallible
18681927
}
18691928
};
18701929
let lldiscr = discr_datum.to_zeroable_ref_llval(bcx);
@@ -1892,15 +1951,6 @@ fn trans_match_inner(scope_cx: @mut Block,
18921951

18931952
bcx = controlflow::join_blocks(scope_cx, arm_cxs);
18941953
return bcx;
1895-
1896-
fn mk_fail(bcx: @mut Block, sp: Span, msg: @str,
1897-
finished: @mut Option<BasicBlockRef>) -> BasicBlockRef {
1898-
match *finished { Some(bb) => return bb, _ => () }
1899-
let fail_cx = sub_block(bcx, "case_fallthrough");
1900-
controlflow::trans_fail(fail_cx, Some(sp), msg);
1901-
*finished = Some(fail_cx.llbb);
1902-
return fail_cx.llbb;
1903-
}
19041954
}
19051955

19061956
enum IrrefutablePatternBindingMode {
@@ -1913,7 +1963,7 @@ enum IrrefutablePatternBindingMode {
19131963
pub fn store_local(bcx: @mut Block,
19141964
pat: @ast::Pat,
19151965
opt_init_expr: Option<@ast::Expr>)
1916-
-> @mut Block {
1966+
-> @mut Block {
19171967
/*!
19181968
* Generates code for a local variable declaration like
19191969
* `let <pat>;` or `let <pat> = <opt_init_expr>`.

0 commit comments

Comments
 (0)