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