@@ -33,7 +33,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
3333 PatternKind :: Variant { ref adt_def, variant_index : _, subpatterns : _ } => {
3434 Test {
3535 span : match_pair. pattern . span ,
36- kind : TestKind :: Switch { adt_def : adt_def. clone ( ) } ,
36+ kind : TestKind :: Switch {
37+ adt_def : adt_def. clone ( ) ,
38+ variants : vec ! [ false ; self . hir. num_variants( adt_def) ] ,
39+ } ,
3740 }
3841 }
3942
@@ -125,9 +128,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
125128 } ) ;
126129 true
127130 }
128-
131+ PatternKind :: Variant { .. } => {
132+ panic ! ( "you should have called add_cases_to_switch_switch instead!" ) ;
133+ }
129134 PatternKind :: Range { .. } |
130- PatternKind :: Variant { .. } |
131135 PatternKind :: Slice { .. } |
132136 PatternKind :: Array { .. } |
133137 PatternKind :: Wild |
@@ -140,6 +144,30 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
140144 }
141145 }
142146
147+ pub fn add_variants_to_switch < ' pat > ( & mut self ,
148+ test_lvalue : & Lvalue < ' tcx > ,
149+ candidate : & Candidate < ' pat , ' tcx > ,
150+ variants : & mut Vec < bool > )
151+ -> bool
152+ {
153+ let match_pair = match candidate. match_pairs . iter ( ) . find ( |mp| mp. lvalue == * test_lvalue) {
154+ Some ( match_pair) => match_pair,
155+ _ => { return false ; }
156+ } ;
157+
158+ match * match_pair. pattern . kind {
159+ PatternKind :: Variant { adt_def : _ , variant_index, .. } => {
160+ // Do I need to look at the PatternKind::Variant subpatterns?
161+ variants[ variant_index] |= true ;
162+ true
163+ }
164+ _ => {
165+ // don't know how to add these patterns to a switch
166+ false
167+ }
168+ }
169+ }
170+
143171 /// Generates the code to perform a test.
144172 pub fn perform_test ( & mut self ,
145173 block : BasicBlock ,
@@ -148,11 +176,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
148176 -> Vec < BasicBlock > {
149177 let scope_id = self . innermost_scope_id ( ) ;
150178 match test. kind {
151- TestKind :: Switch { adt_def } => {
179+ TestKind :: Switch { adt_def, ref variants } => {
152180 let num_enum_variants = self . hir . num_variants ( adt_def) ;
153- let target_blocks: Vec < _ > =
181+ debug ! ( "num_enum_variants: {}" , num_enum_variants) ;
182+ debug ! ( "variants.len(): {}" , variants. len( ) ) ;
183+ debug ! ( "variants: {:?}" , variants) ;
184+ let target_blocks: Vec < _ > = if variants. into_iter ( ) . any ( |b| { !b} ) {
185+ let otherwise_block = self . cfg . start_new_block ( ) ;
186+ debug ! ( "basic block: {:?} is an otherwise block!" , otherwise_block) ;
187+ ( 0 ..num_enum_variants) . map ( |i|
188+ if variants[ i] {
189+ self . cfg . start_new_block ( )
190+ } else {
191+ otherwise_block
192+ }
193+ )
194+ . collect ( )
195+ } else {
154196 ( 0 ..num_enum_variants) . map ( |_| self . cfg . start_new_block ( ) )
155- . collect ( ) ;
197+ . collect ( )
198+ } ;
156199 self . cfg . terminate ( block, scope_id, test. span , TerminatorKind :: Switch {
157200 discr : lvalue. clone ( ) ,
158201 adt_def : adt_def,
@@ -383,7 +426,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
383426 match test. kind {
384427 // If we are performing a variant switch, then this
385428 // informs variant patterns, but nothing else.
386- TestKind :: Switch { adt_def : tested_adt_def } => {
429+ TestKind :: Switch { adt_def : tested_adt_def , .. } => {
387430 match * match_pair. pattern . kind {
388431 PatternKind :: Variant { adt_def, variant_index, ref subpatterns } => {
389432 assert_eq ! ( adt_def, tested_adt_def) ;
0 commit comments