@@ -533,7 +533,7 @@ fn enter_default<'r>(bcx: @mut Block,
533
533
m : & [ Match < ' r > ] ,
534
534
col : uint ,
535
535
val : ValueRef ,
536
- chk : Option < mk_fail > )
536
+ chk : FailureHandler )
537
537
-> ~[ Match < ' r > ] {
538
538
debug ! ( "enter_default(bcx=%s, m=%s, col=%u, val=%s)" ,
539
539
bcx. to_str( ) ,
@@ -567,7 +567,7 @@ fn enter_default<'r>(bcx: @mut Block,
567
567
// we don't need any default cases. If the check *isn't* nonexhaustive
568
568
// (because chk is Some), then we need the defaults anyways.
569
569
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 ,
571
571
_ => false
572
572
} ;
573
573
@@ -1185,7 +1185,62 @@ fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
1185
1185
}
1186
1186
}
1187
1187
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
+ }
1189
1244
1190
1245
fn pick_col ( m : & [ Match ] ) -> uint {
1191
1246
fn score ( p : & ast:: Pat ) -> uint {
@@ -1347,7 +1402,7 @@ fn compile_guard(bcx: @mut Block,
1347
1402
data : & ArmData ,
1348
1403
m : & [ Match ] ,
1349
1404
vals : & [ ValueRef ] ,
1350
- chk : Option < mk_fail > )
1405
+ chk : FailureHandler )
1351
1406
-> @mut Block {
1352
1407
debug ! ( "compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%s)" ,
1353
1408
bcx. to_str( ) ,
@@ -1400,9 +1455,9 @@ fn compile_guard(bcx: @mut Block,
1400
1455
}
1401
1456
1402
1457
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 ) {
1406
1461
debug ! ( "compile_submatch(bcx=%s, m=%s, vals=%s)" ,
1407
1462
bcx. to_str( ) ,
1408
1463
m. repr( bcx. tcx( ) ) ,
@@ -1412,11 +1467,11 @@ fn compile_submatch(bcx: @mut Block,
1412
1467
/*
1413
1468
For an empty match, a fall-through case must exist
1414
1469
*/
1415
- assert ! ( ( m. len( ) > 0 u || chk. is_some ( ) ) ) ;
1470
+ assert ! ( ( m. len( ) > 0 u || chk. is_fallible ( ) ) ) ;
1416
1471
let _icx = push_ctxt ( "match::compile_submatch" ) ;
1417
1472
let mut bcx = bcx;
1418
1473
if m. len ( ) == 0 u {
1419
- Br ( bcx, chk. unwrap ( ) ( ) ) ;
1474
+ Br ( bcx, chk. handle_fail ( ) ) ;
1420
1475
return ;
1421
1476
}
1422
1477
if m[ 0 ] . pats . len ( ) == 0 u {
@@ -1454,7 +1509,7 @@ fn compile_submatch(bcx: @mut Block,
1454
1509
fn compile_submatch_continue ( mut bcx : @mut Block ,
1455
1510
m : & [ Match ] ,
1456
1511
vals : & [ ValueRef ] ,
1457
- chk : Option < mk_fail > ,
1512
+ chk : FailureHandler ,
1458
1513
col : uint ,
1459
1514
val : ValueRef ) {
1460
1515
let tcx = bcx. tcx ( ) ;
@@ -1617,7 +1672,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
1617
1672
} ;
1618
1673
1619
1674
let defaults = enter_default ( else_cx, dm, m, col, val, chk) ;
1620
- let exhaustive = chk. is_none ( ) && defaults. len ( ) == 0 u;
1675
+ let exhaustive = chk. is_infallible ( ) && defaults. len ( ) == 0 u;
1621
1676
let len = opts. len ( ) ;
1622
1677
1623
1678
// Compile subtrees for each option
@@ -1721,7 +1776,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
1721
1776
1722
1777
// If none of these subcases match, move on to the
1723
1778
// next condition.
1724
- branch_chk = Some :: < mk_fail > ( || bcx. llbb ) ;
1779
+ branch_chk = JumpToBasicBlock ( bcx. llbb ) ;
1725
1780
CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
1726
1781
}
1727
1782
_ => ( )
@@ -1860,11 +1915,15 @@ fn trans_match_inner(scope_cx: @mut Block,
1860
1915
if ty:: type_is_empty ( tcx, t) {
1861
1916
// Special case for empty types
1862
1917
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)
1866
1925
} else {
1867
- None
1926
+ Infallible
1868
1927
}
1869
1928
} ;
1870
1929
let lldiscr = discr_datum. to_zeroable_ref_llval ( bcx) ;
@@ -1892,15 +1951,6 @@ fn trans_match_inner(scope_cx: @mut Block,
1892
1951
1893
1952
bcx = controlflow:: join_blocks ( scope_cx, arm_cxs) ;
1894
1953
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
- }
1904
1954
}
1905
1955
1906
1956
enum IrrefutablePatternBindingMode {
@@ -1913,7 +1963,7 @@ enum IrrefutablePatternBindingMode {
1913
1963
pub fn store_local( bcx : @mut Block ,
1914
1964
pat : @ast:: Pat ,
1915
1965
opt_init_expr : Option < @ast:: Expr > )
1916
- -> @mut Block {
1966
+ -> @mut Block {
1917
1967
/*!
1918
1968
* Generates code for a local variable declaration like
1919
1969
* `let <pat>;` or `let <pat> = <opt_init_expr>`.
0 commit comments