@@ -640,35 +640,16 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
640
640
f : val_and_ty_fn ) -> block {
641
641
let _icx = cx. insn_ctxt ( "iter_structural_ty" ) ;
642
642
643
- fn iter_variant ( cx : block , a_tup : ValueRef ,
643
+ fn iter_variant ( cx : block , repr : & adt :: Repr , av : ValueRef ,
644
644
variant : ty:: VariantInfo ,
645
- tps : & [ ty:: t ] , tid : ast:: def_id ,
646
- f : val_and_ty_fn ) -> block {
645
+ tps : & [ ty:: t ] , f : val_and_ty_fn ) -> block {
647
646
let _icx = cx. insn_ctxt ( "iter_variant" ) ;
648
- if variant. args . len ( ) == 0 u { return cx; }
649
- let fn_ty = variant. ctor_ty ;
650
- let ccx = cx. ccx ( ) ;
647
+ let tcx = cx. tcx ( ) ;
651
648
let mut cx = cx;
652
- match ty:: get ( fn_ty) . sty {
653
- ty:: ty_bare_fn( ref fn_ty) => {
654
- let mut j = 0 u;
655
- let v_id = variant. id ;
656
- for vec:: each( fn_ty. sig. inputs) |a| {
657
- let llfldp_a = GEP_enum ( cx, a_tup, tid, v_id,
658
- /*bad*/ copy tps, j) ;
659
- // This assumes the self type is absent (it passes
660
- // None for the self_ty_opt arg of substs_tps).
661
- // I think that's ok since you can't have an enum
662
- // inside a trait.
663
- let ty_subst = ty:: subst_tps ( ccx. tcx , tps, None , a. ty ) ;
664
- cx = f ( cx, llfldp_a, ty_subst) ;
665
- j += 1 u;
666
- }
667
- }
668
- _ => cx. tcx ( ) . sess . bug ( fmt ! ( "iter_variant: not a function type: \
669
- %s (variant name = %s)",
670
- cx. ty_to_str( fn_ty) ,
671
- * cx. sess( ) . str_of( variant. name) ) )
649
+
650
+ for variant. args. eachi |i, & arg| {
651
+ cx = f ( cx, adt:: trans_GEP ( cx, repr, av, variant. disr_val , i) ,
652
+ ty:: subst_tps ( tcx, tps, None , arg) ) ;
672
653
}
673
654
return cx;
674
655
}
@@ -697,45 +678,49 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
697
678
}
698
679
}
699
680
ty:: ty_enum( tid, ref substs) => {
700
- let variants = ty:: enum_variants ( cx. tcx ( ) , tid) ;
701
- let n_variants = ( * variants) . len ( ) ;
702
-
703
- // Cast the enums to types we can GEP into.
704
- if n_variants == 1 u {
705
- return iter_variant ( cx,
706
- av,
707
- variants[ 0 ] ,
708
- /*bad*/ copy substs. tps ,
709
- tid,
710
- f) ;
711
- }
681
+ let ccx = cx. ccx ( ) ;
712
682
713
- let ccx = cx. ccx ( ) ;
714
- let llenumty = T_opaque_enum_ptr ( ccx) ;
715
- let av_enum = PointerCast ( cx, av, llenumty) ;
716
- let lldiscrim_a_ptr = GEPi ( cx, av_enum, [ 0 u, 0 u] ) ;
717
- let llunion_a_ptr = GEPi ( cx, av_enum, [ 0 u, 1 u] ) ;
718
- let lldiscrim_a = Load ( cx, lldiscrim_a_ptr) ;
719
-
720
- // NB: we must hit the discriminant first so that structural
721
- // comparison know not to proceed when the discriminants differ.
722
- cx = f ( cx, lldiscrim_a_ptr, ty:: mk_int ( cx. tcx ( ) ) ) ;
723
- let unr_cx = sub_block ( cx, ~"enum -iter-unr") ;
724
- Unreachable ( unr_cx) ;
725
- let llswitch = Switch ( cx, lldiscrim_a, unr_cx. llbb , n_variants) ;
726
- let next_cx = sub_block ( cx, ~"enum -iter-next") ;
727
- for vec:: each( * variants) |variant| {
728
- let variant_cx =
729
- sub_block ( cx,
730
- ~"enum -iter-variant-" +
731
- int::to_str(variant.disr_val));
732
- AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb);
733
- let variant_cx =
734
- iter_variant(variant_cx, llunion_a_ptr, *variant,
735
- /*bad*/copy (*substs).tps, tid, f);
736
- Br(variant_cx, next_cx.llbb);
737
- }
738
- return next_cx;
683
+ let repr = adt:: represent_type ( ccx, t) ;
684
+ let variants = ty:: enum_variants ( ccx. tcx , tid) ;
685
+ let n_variants = ( * variants) . len ( ) ;
686
+
687
+ // NB: we must hit the discriminant first so that structural
688
+ // comparison know not to proceed when the discriminants differ.
689
+
690
+ match adt:: trans_switch ( cx, & repr, av) {
691
+ ( _match:: single, None ) => {
692
+ cx = iter_variant ( cx, & repr, av, variants[ 0 ] ,
693
+ substs. tps , f) ;
694
+ }
695
+ ( _match:: switch, Some ( lldiscrim_a) ) => {
696
+ cx = f ( cx, lldiscrim_a, ty:: mk_int ( cx. tcx ( ) ) ) ;
697
+ let unr_cx = sub_block ( cx, ~"enum -iter-unr") ;
698
+ Unreachable ( unr_cx) ;
699
+ let llswitch = Switch ( cx, lldiscrim_a, unr_cx. llbb ,
700
+ n_variants) ;
701
+ let next_cx = sub_block ( cx, ~"enum -iter-next") ;
702
+
703
+ for vec:: each( * variants) |variant| {
704
+ let variant_cx =
705
+ sub_block ( cx, ~"enum -iter-variant-" +
706
+ int::to_str(variant.disr_val));
707
+ let variant_cx =
708
+ iter_variant(variant_cx, &repr, av, *variant,
709
+ substs.tps, f);
710
+ match adt::trans_case(cx, &repr, variant.disr_val) {
711
+ _match::single_result(r) => {
712
+ AddCase(llswitch, r.val, variant_cx.llbb)
713
+ }
714
+ _ => ccx.sess.unimpl(~"value from adt:: trans_case \
715
+ in iter_structural_ty" )
716
+ }
717
+ Br ( variant_cx, next_cx. llbb ) ;
718
+ }
719
+ cx = next_cx;
720
+ }
721
+ _ => ccx. sess . unimpl ( ~"value from adt:: trans_switch \
722
+ in iter_structural_ty")
723
+ }
739
724
}
740
725
_ => cx. sess ( ) . unimpl ( ~"type in iter_structural_ty")
741
726
}
0 commit comments