@@ -202,12 +202,12 @@ use middle::resolve::DefMap;
202
202
use middle:: trans:: adt;
203
203
use middle:: trans:: base:: * ;
204
204
use middle:: trans:: build:: * ;
205
- use middle:: trans:: build;
206
205
use middle:: trans:: callee;
207
206
use middle:: trans:: cleanup;
208
207
use middle:: trans:: cleanup:: CleanupMethods ;
209
208
use middle:: trans:: common:: * ;
210
209
use middle:: trans:: consts;
210
+ use middle:: trans:: controlflow;
211
211
use middle:: trans:: datum:: * ;
212
212
use middle:: trans:: expr:: Dest ;
213
213
use middle:: trans:: expr;
@@ -220,12 +220,14 @@ use util::ppaux::{Repr, vec_map_to_string};
220
220
221
221
use std;
222
222
use std:: collections:: HashMap ;
223
+ use std:: cell:: Cell ;
223
224
use std:: rc:: Rc ;
224
225
use std:: gc:: { Gc } ;
225
226
use syntax:: ast;
226
227
use syntax:: ast:: Ident ;
227
228
use syntax:: codemap:: Span ;
228
229
use syntax:: fold:: Folder ;
230
+ use syntax:: parse:: token:: InternedString ;
229
231
230
232
#[ deriving( PartialEq ) ]
231
233
pub enum VecLenOpt {
@@ -299,6 +301,20 @@ fn trans_opt<'a>(mut bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
299
301
}
300
302
}
301
303
304
+ fn variant_opt ( bcx : & Block , pat_id : ast:: NodeId ) -> Opt {
305
+ let ccx = bcx. ccx ( ) ;
306
+ let def = ccx. tcx . def_map . borrow ( ) . get_copy ( & pat_id) ;
307
+ match def {
308
+ def:: DefVariant ( enum_id, var_id, _) => {
309
+ let variant = ty:: enum_variant_with_id ( ccx. tcx ( ) , enum_id, var_id) ;
310
+ var ( variant. disr_val , adt:: represent_node ( bcx, pat_id) , var_id)
311
+ }
312
+ _ => {
313
+ ccx. sess ( ) . bug ( "non-variant or struct in variant_opt()" ) ;
314
+ }
315
+ }
316
+ }
317
+
302
318
#[ deriving( Clone ) ]
303
319
pub enum TransBindingMode {
304
320
TrByCopy ( /* llbinding */ ValueRef ) ,
@@ -614,15 +630,26 @@ fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec<Opt> {
614
630
ast:: PatLit ( l) => {
615
631
add_to_set ( ccx. tcx ( ) , & mut found, lit ( l) ) ;
616
632
}
617
- ast:: PatIdent ( ..) | ast :: PatEnum ( .. ) | ast :: PatStruct ( .. ) => {
633
+ ast:: PatIdent ( ..) => {
618
634
// This is either an enum variant or a variable binding.
619
635
let opt_def = ccx. tcx . def_map . borrow ( ) . find_copy ( & cur. id ) ;
620
636
match opt_def {
621
- Some ( def:: DefVariant ( enum_id, var_id, _) ) => {
622
- let variant = ty:: enum_variant_with_id ( ccx. tcx ( ) , enum_id, var_id) ;
637
+ Some ( def:: DefVariant ( ..) ) => {
638
+ add_to_set ( ccx. tcx ( ) , & mut found,
639
+ variant_opt ( bcx, cur. id ) ) ;
640
+ }
641
+ _ => { }
642
+ }
643
+ }
644
+ ast:: PatEnum ( ..) | ast:: PatStruct ( ..) => {
645
+ // This could be one of: a tuple-like enum variant, a
646
+ // struct-like enum variant, or a struct.
647
+ let opt_def = ccx. tcx . def_map . borrow ( ) . find_copy ( & cur. id ) ;
648
+ match opt_def {
649
+ Some ( def:: DefFn ( ..) ) |
650
+ Some ( def:: DefVariant ( ..) ) => {
623
651
add_to_set ( ccx. tcx ( ) , & mut found,
624
- var ( variant. disr_val ,
625
- adt:: represent_node ( bcx, cur. id ) , var_id) ) ;
652
+ variant_opt ( bcx, cur. id ) ) ;
626
653
}
627
654
_ => { }
628
655
}
@@ -768,33 +795,56 @@ fn any_irrefutable_adt_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
768
795
} )
769
796
}
770
797
798
+ struct DynamicFailureHandler < ' a > {
799
+ bcx : & ' a Block < ' a > ,
800
+ sp : Span ,
801
+ msg : InternedString ,
802
+ finished : Cell < Option < BasicBlockRef > > ,
803
+ }
804
+
805
+ impl < ' a > DynamicFailureHandler < ' a > {
806
+ fn handle_fail ( & self ) -> BasicBlockRef {
807
+ match self . finished . get ( ) {
808
+ Some ( bb) => return bb,
809
+ _ => ( ) ,
810
+ }
811
+
812
+ let fcx = self . bcx . fcx ;
813
+ let fail_cx = fcx. new_block ( false , "case_fallthrough" , None ) ;
814
+ controlflow:: trans_fail ( fail_cx, self . sp , self . msg . clone ( ) ) ;
815
+ self . finished . set ( Some ( fail_cx. llbb ) ) ;
816
+ fail_cx. llbb
817
+ }
818
+ }
819
+
771
820
/// What to do when the pattern match fails.
772
821
enum FailureHandler < ' a > {
773
822
Infallible ,
774
823
JumpToBasicBlock ( BasicBlockRef ) ,
775
- Unreachable
824
+ DynamicFailureHandlerClass ( Box < DynamicFailureHandler < ' a > > ) ,
776
825
}
777
826
778
827
impl < ' a > FailureHandler < ' a > {
779
828
fn is_infallible ( & self ) -> bool {
780
829
match * self {
781
830
Infallible => true ,
782
- _ => false
831
+ _ => false ,
783
832
}
784
833
}
785
834
786
835
fn is_fallible ( & self ) -> bool {
787
836
!self . is_infallible ( )
788
837
}
789
838
790
- fn handle_fail ( & self , bcx : & Block ) {
839
+ fn handle_fail ( & self ) -> BasicBlockRef {
791
840
match * self {
792
- Infallible =>
793
- fail ! ( "attempted to fail in infallible failure handler!" ) ,
794
- JumpToBasicBlock ( basic_block) =>
795
- Br ( bcx, basic_block) ,
796
- Unreachable =>
797
- build:: Unreachable ( bcx)
841
+ Infallible => {
842
+ fail ! ( "attempted to fail in infallible failure handler!" )
843
+ }
844
+ JumpToBasicBlock ( basic_block) => basic_block,
845
+ DynamicFailureHandlerClass ( ref dynamic_failure_handler) => {
846
+ dynamic_failure_handler. handle_fail ( )
847
+ }
798
848
}
799
849
}
800
850
}
@@ -955,7 +1005,7 @@ fn compile_guard<'a, 'b>(
955
1005
// condition explicitly rather than (possibly) falling back to
956
1006
// the default arm.
957
1007
& JumpToBasicBlock ( _) if m. len ( ) == 1 && has_genuine_default => {
958
- chk. handle_fail ( bcx ) ;
1008
+ Br ( bcx , chk. handle_fail ( ) ) ;
959
1009
}
960
1010
_ => {
961
1011
compile_submatch ( bcx, m, vals, chk, has_genuine_default) ;
@@ -980,7 +1030,7 @@ fn compile_submatch<'a, 'b>(
980
1030
let mut bcx = bcx;
981
1031
if m. len ( ) == 0 u {
982
1032
if chk. is_fallible ( ) {
983
- chk. handle_fail ( bcx ) ;
1033
+ Br ( bcx , chk. handle_fail ( ) ) ;
984
1034
}
985
1035
return ;
986
1036
}
@@ -1251,7 +1301,7 @@ fn compile_submatch_continue<'a, 'b>(
1251
1301
// condition explicitly rather than (eventually) falling back to
1252
1302
// the last default arm.
1253
1303
& JumpToBasicBlock ( _) if defaults. len ( ) == 1 && has_genuine_default => {
1254
- chk. handle_fail ( else_cx ) ;
1304
+ Br ( else_cx , chk. handle_fail ( ) ) ;
1255
1305
}
1256
1306
_ => {
1257
1307
compile_submatch ( else_cx,
@@ -1345,10 +1395,21 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
1345
1395
}
1346
1396
1347
1397
let t = node_id_type ( bcx, discr_expr. id ) ;
1348
- let chk = if ty:: type_is_empty ( tcx, t) {
1349
- Unreachable
1350
- } else {
1351
- Infallible
1398
+ let chk = {
1399
+ if ty:: type_is_empty ( tcx, t) {
1400
+ // Special case for empty types
1401
+ let fail_cx = Cell :: new ( None ) ;
1402
+ let fail_handler = box DynamicFailureHandler {
1403
+ bcx : scope_cx,
1404
+ sp : discr_expr. span ,
1405
+ msg : InternedString :: new ( "scrutinizing value that can't \
1406
+ exist") ,
1407
+ finished : fail_cx,
1408
+ } ;
1409
+ DynamicFailureHandlerClass ( fail_handler)
1410
+ } else {
1411
+ Infallible
1412
+ }
1352
1413
} ;
1353
1414
1354
1415
let arm_datas: Vec < ArmData > = arms. iter ( ) . map ( |arm| ArmData {
0 commit comments