@@ -850,7 +850,12 @@ fn fn_data_to_datum(bcx: block,
850
850
return bcx;
851
851
}
852
852
853
- fn with_field_tys < R > ( tcx : ty:: ctxt , ty : ty:: t ,
853
+ // The optional node ID here is the node ID of the path identifying the enum
854
+ // variant in use. If none, this cannot possibly an enum variant (so, if it
855
+ // is and `node_id_opt` is none, this function fails).
856
+ fn with_field_tys < R > ( tcx : ty:: ctxt ,
857
+ ty : ty:: t ,
858
+ node_id_opt : Option < ast:: node_id > ,
854
859
op : fn ( bool , ( & [ ty:: field ] ) ) -> R ) -> R {
855
860
match ty:: get ( ty) . sty {
856
861
ty:: ty_rec( ref fields) => {
@@ -862,6 +867,30 @@ fn with_field_tys<R>(tcx: ty::ctxt, ty: ty::t,
862
867
op ( has_dtor, class_items_as_mutable_fields ( tcx, did, substs) )
863
868
}
864
869
870
+ ty:: ty_enum( _, ref substs) => {
871
+ // We want the *variant* ID here, not the enum ID.
872
+ match node_id_opt {
873
+ None => {
874
+ tcx. sess . bug ( fmt ! (
875
+ "cannot get field types from the enum type %s \
876
+ without a node ID",
877
+ ty_to_str( tcx, ty) ) ) ;
878
+ }
879
+ Some ( node_id) => {
880
+ match tcx. def_map . get ( node_id) {
881
+ ast:: def_variant( _, variant_id) => {
882
+ op ( false , class_items_as_mutable_fields (
883
+ tcx, variant_id, substs) )
884
+ }
885
+ _ => {
886
+ tcx. sess . bug ( ~"resolve didn' t map this expr to a \
887
+ variant ID ")
888
+ }
889
+ }
890
+ }
891
+ }
892
+ }
893
+
865
894
_ => {
866
895
tcx. sess . bug ( fmt ! (
867
896
"cannot get field types from the type %s" ,
@@ -877,7 +906,7 @@ fn trans_rec_field(bcx: block,
877
906
let _icx = bcx. insn_ctxt ( "trans_rec_field" ) ;
878
907
879
908
let base_datum = unpack_datum ! ( bcx, trans_to_datum( bcx, base) ) ;
880
- do with_field_tys ( bcx. tcx ( ) , base_datum. ty ) |_has_dtor , field_tys| {
909
+ do with_field_tys ( bcx. tcx ( ) , base_datum. ty , None ) |_dtor , field_tys| {
881
910
let ix = ty:: field_idx_strict ( bcx. tcx ( ) , field, field_tys) ;
882
911
DatumBlock {
883
912
datum : base_datum. GEPi ( bcx, [ 0 u, 0 u, ix] , field_tys[ ix] . mt . ty ) ,
@@ -969,9 +998,45 @@ fn trans_rec_or_struct(bcx: block,
969
998
}
970
999
}
971
1000
1001
+ // If this is a struct-like variant, write in the discriminant if
1002
+ // necessary, position the address at the right location, and cast the
1003
+ // address.
972
1004
let ty = node_id_type ( bcx, id) ;
973
1005
let tcx = bcx. tcx ( ) ;
974
- do with_field_tys ( tcx, ty) |has_dtor, field_tys| {
1006
+ let addr = match ty:: get ( ty) . sty {
1007
+ ty:: ty_enum( _, ref substs) => {
1008
+ match tcx. def_map . get ( id) {
1009
+ ast:: def_variant( enum_id, variant_id) => {
1010
+ let variant_info = ty:: enum_variant_with_id (
1011
+ tcx, enum_id, variant_id) ;
1012
+ let addr = if ty:: enum_is_univariant ( tcx, enum_id) {
1013
+ addr
1014
+ } else {
1015
+ Store ( bcx,
1016
+ C_int ( bcx. ccx ( ) , variant_info. disr_val ) ,
1017
+ GEPi ( bcx, addr, [ 0 , 0 ] ) ) ;
1018
+ GEPi ( bcx, addr, [ 0 , 1 ] )
1019
+ } ;
1020
+ let fields = ty:: class_items_as_mutable_fields (
1021
+ tcx, variant_id, substs) ;
1022
+ let field_lltys = do fields. map |field| {
1023
+ type_of ( bcx. ccx ( ) ,
1024
+ ty:: subst_tps (
1025
+ tcx, substs. tps , None , field. mt . ty ) )
1026
+ } ;
1027
+ PointerCast ( bcx, addr,
1028
+ T_ptr ( T_struct ( ~[ T_struct ( field_lltys) ] ) ) )
1029
+ }
1030
+ _ => {
1031
+ tcx. sess . bug ( ~"resolve didn' t write the right def in for \
1032
+ this struct-like variant")
1033
+ }
1034
+ }
1035
+ }
1036
+ _ => addr
1037
+ } ;
1038
+
1039
+ do with_field_tys( tcx, ty, Some ( id) ) |has_dtor, field_tys| {
975
1040
// evaluate each of the fields and store them into their
976
1041
// correct locations
977
1042
let mut temp_cleanups = ~[ ] ;
0 commit comments