@@ -19,6 +19,7 @@ use build::Builder;
1919use build:: matches:: { Candidate , MatchPair , Test , TestKind } ;
2020use hair:: * ;
2121use rustc_data_structures:: fnv:: FnvHashMap ;
22+ use rustc_data_structures:: bitvec:: BitVector ;
2223use rustc:: middle:: const_val:: ConstVal ;
2324use rustc:: ty:: { self , Ty } ;
2425use rustc:: mir:: repr:: * ;
@@ -33,7 +34,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
3334 PatternKind :: Variant { ref adt_def, variant_index : _, subpatterns : _ } => {
3435 Test {
3536 span : match_pair. pattern . span ,
36- kind : TestKind :: Switch { adt_def : adt_def. clone ( ) } ,
37+ kind : TestKind :: Switch {
38+ adt_def : adt_def. clone ( ) ,
39+ variants : BitVector :: new ( self . hir . num_variants ( adt_def) ) ,
40+ } ,
3741 }
3842 }
3943
@@ -125,9 +129,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
125129 } ) ;
126130 true
127131 }
128-
132+ PatternKind :: Variant { .. } => {
133+ panic ! ( "you should have called add_variants_to_switch instead!" ) ;
134+ }
129135 PatternKind :: Range { .. } |
130- PatternKind :: Variant { .. } |
131136 PatternKind :: Slice { .. } |
132137 PatternKind :: Array { .. } |
133138 PatternKind :: Wild |
@@ -140,6 +145,31 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
140145 }
141146 }
142147
148+ pub fn add_variants_to_switch < ' pat > ( & mut self ,
149+ test_lvalue : & Lvalue < ' tcx > ,
150+ candidate : & Candidate < ' pat , ' tcx > ,
151+ variants : & mut BitVector )
152+ -> bool
153+ {
154+ let match_pair = match candidate. match_pairs . iter ( ) . find ( |mp| mp. lvalue == * test_lvalue) {
155+ Some ( match_pair) => match_pair,
156+ _ => { return false ; }
157+ } ;
158+
159+ match * match_pair. pattern . kind {
160+ PatternKind :: Variant { adt_def : _ , variant_index, .. } => {
161+ // We have a pattern testing for variant `variant_index`
162+ // set the corresponding index to true
163+ variants. insert ( variant_index) ;
164+ true
165+ }
166+ _ => {
167+ // don't know how to add these patterns to a switch
168+ false
169+ }
170+ }
171+ }
172+
143173 /// Generates the code to perform a test.
144174 pub fn perform_test ( & mut self ,
145175 block : BasicBlock ,
@@ -148,11 +178,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
148178 -> Vec < BasicBlock > {
149179 let scope_id = self . innermost_scope_id ( ) ;
150180 match test. kind {
151- TestKind :: Switch { adt_def } => {
181+ TestKind :: Switch { adt_def, ref variants } => {
152182 let num_enum_variants = self . hir . num_variants ( adt_def) ;
153- let target_blocks: Vec < _ > =
154- ( 0 ..num_enum_variants) . map ( |_| self . cfg . start_new_block ( ) )
155- . collect ( ) ;
183+ let mut otherwise_block = None ;
184+ let target_blocks: Vec < _ > = ( 0 ..num_enum_variants) . map ( |i| {
185+ if variants. contains ( i) {
186+ self . cfg . start_new_block ( )
187+ } else {
188+ if otherwise_block. is_none ( ) {
189+ otherwise_block = Some ( self . cfg . start_new_block ( ) ) ;
190+ }
191+ otherwise_block. unwrap ( )
192+ }
193+ } ) . collect ( ) ;
194+ debug ! ( "num_enum_variants: {}, num tested variants: {}, variants: {:?}" ,
195+ num_enum_variants, variants. iter( ) . count( ) , variants) ;
156196 self . cfg . terminate ( block, scope_id, test. span , TerminatorKind :: Switch {
157197 discr : lvalue. clone ( ) ,
158198 adt_def : adt_def,
@@ -415,7 +455,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
415455 match test. kind {
416456 // If we are performing a variant switch, then this
417457 // informs variant patterns, but nothing else.
418- TestKind :: Switch { adt_def : tested_adt_def } => {
458+ TestKind :: Switch { adt_def : tested_adt_def , .. } => {
419459 match * match_pair. pattern . kind {
420460 PatternKind :: Variant { adt_def, variant_index, ref subpatterns } => {
421461 assert_eq ! ( adt_def, tested_adt_def) ;
0 commit comments