@@ -746,18 +746,17 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
746746 controlflow:: trans_block ( bcx, & * * blk, dest)
747747 }
748748 ast:: ExprStruct ( _, ref fields, base) => {
749- trans_rec_or_struct ( bcx,
750- fields. as_slice ( ) ,
751- base,
752- expr. span ,
753- expr. id ,
754- dest)
749+ trans_struct ( bcx,
750+ fields. as_slice ( ) ,
751+ base,
752+ expr. span ,
753+ expr. id ,
754+ dest)
755755 }
756756 ast:: ExprTup ( ref args) => {
757- let repr = adt:: represent_type ( bcx. ccx ( ) , expr_ty ( bcx, expr) ) ;
758757 let numbered_fields: Vec < ( uint , Gc < ast:: Expr > ) > =
759758 args. iter ( ) . enumerate ( ) . map ( |( i, arg) | ( i, * arg) ) . collect ( ) ;
760- trans_adt ( bcx, & * repr , 0 , numbered_fields. as_slice ( ) , None , dest)
759+ trans_adt ( bcx, expr_ty ( bcx , expr ) , 0 , numbered_fields. as_slice ( ) , None , dest)
761760 }
762761 ast:: ExprLit ( lit) => {
763762 match lit. node {
@@ -1042,16 +1041,13 @@ pub fn with_field_tys<R>(tcx: &ty::ctxt,
10421041 }
10431042}
10441043
1045- fn trans_rec_or_struct < ' a > (
1046- bcx : & ' a Block < ' a > ,
1047- fields : & [ ast:: Field ] ,
1048- base : Option < Gc < ast:: Expr > > ,
1049- expr_span : codemap:: Span ,
1050- id : ast:: NodeId ,
1051- dest : Dest )
1052- -> & ' a Block < ' a > {
1044+ fn trans_struct < ' a > ( bcx : & ' a Block < ' a > ,
1045+ fields : & [ ast:: Field ] ,
1046+ base : Option < Gc < ast:: Expr > > ,
1047+ expr_span : codemap:: Span ,
1048+ id : ast:: NodeId ,
1049+ dest : Dest ) -> & ' a Block < ' a > {
10531050 let _icx = push_ctxt ( "trans_rec" ) ;
1054- let bcx = bcx;
10551051
10561052 let ty = node_id_type ( bcx, id) ;
10571053 let tcx = bcx. tcx ( ) ;
@@ -1092,8 +1088,7 @@ fn trans_rec_or_struct<'a>(
10921088 }
10931089 } ;
10941090
1095- let repr = adt:: represent_type ( bcx. ccx ( ) , ty) ;
1096- trans_adt ( bcx, & * repr, discr, numbered_fields. as_slice ( ) , optbase, dest)
1091+ trans_adt ( bcx, ty, discr, numbered_fields. as_slice ( ) , optbase, dest)
10971092 } )
10981093}
10991094
@@ -1121,60 +1116,71 @@ pub struct StructBaseInfo {
11211116 * - `optbase` contains information on the base struct (if any) from
11221117 * which remaining fields are copied; see comments on `StructBaseInfo`.
11231118 */
1124- pub fn trans_adt < ' a > ( bcx : & ' a Block < ' a > ,
1125- repr : & adt :: Repr ,
1119+ pub fn trans_adt < ' a > ( mut bcx : & ' a Block < ' a > ,
1120+ ty : ty :: t ,
11261121 discr : ty:: Disr ,
11271122 fields : & [ ( uint , Gc < ast:: Expr > ) ] ,
11281123 optbase : Option < StructBaseInfo > ,
11291124 dest : Dest ) -> & ' a Block < ' a > {
11301125 let _icx = push_ctxt ( "trans_adt" ) ;
11311126 let fcx = bcx. fcx ;
1132- let mut bcx = bcx;
1127+ let repr = adt:: represent_type ( bcx. ccx ( ) , ty) ;
1128+
1129+ // If we don't care about the result, just make a
1130+ // temporary stack slot
11331131 let addr = match dest {
1134- Ignore => {
1135- for & ( _i, ref e) in fields. iter ( ) {
1136- bcx = trans_into ( bcx, & * * e, Ignore ) ;
1137- }
1138- for sbi in optbase. iter ( ) {
1139- // FIXME #7261: this moves entire base, not just certain fields
1140- bcx = trans_into ( bcx, & * sbi. expr , Ignore ) ;
1141- }
1142- return bcx;
1143- }
1144- SaveIn ( pos) => pos
1132+ SaveIn ( pos) => pos,
1133+ Ignore => alloc_ty ( bcx, ty, "temp" ) ,
11451134 } ;
11461135
11471136 // This scope holds intermediates that must be cleaned should
11481137 // failure occur before the ADT as a whole is ready.
11491138 let custom_cleanup_scope = fcx. push_custom_cleanup_scope ( ) ;
11501139
1140+ // First we trans the base, if we have one, to the dest
1141+ for base in optbase. iter ( ) {
1142+ assert_eq ! ( discr, 0 ) ;
1143+
1144+ match ty:: expr_kind ( bcx. tcx ( ) , & * base. expr ) {
1145+ ty:: LvalueExpr => {
1146+ let base_datum = unpack_datum ! ( bcx, trans_to_lvalue( bcx, & * base. expr, "base" ) ) ;
1147+ for & ( i, t) in base. fields . iter ( ) {
1148+ let datum = base_datum. get_element (
1149+ t, |srcval| adt:: trans_field_ptr ( bcx, & * repr, srcval, discr, i) ) ;
1150+ let dest = adt:: trans_field_ptr ( bcx, & * repr, addr, discr, i) ;
1151+ bcx = datum. store_to ( bcx, dest) ;
1152+ }
1153+ } ,
1154+ ty:: RvalueDpsExpr | ty:: RvalueDatumExpr => {
1155+ bcx = trans_into ( bcx, & * base. expr , SaveIn ( addr) ) ;
1156+ } ,
1157+ ty:: RvalueStmtExpr => bcx. tcx ( ) . sess . bug ( "unexpected expr kind for struct base expr" )
1158+ }
1159+ }
1160+
1161+ // Now, we just overwrite the fields we've explicity specified
11511162 for & ( i, ref e) in fields. iter ( ) {
1152- let dest = adt:: trans_field_ptr ( bcx, repr, addr, discr, i) ;
1163+ let dest = adt:: trans_field_ptr ( bcx, & * repr, addr, discr, i) ;
11531164 let e_ty = expr_ty_adjusted ( bcx, & * * e) ;
11541165 bcx = trans_into ( bcx, & * * e, SaveIn ( dest) ) ;
11551166 let scope = cleanup:: CustomScope ( custom_cleanup_scope) ;
11561167 fcx. schedule_lifetime_end ( scope, dest) ;
11571168 fcx. schedule_drop_mem ( scope, dest, e_ty) ;
11581169 }
11591170
1160- for base in optbase. iter ( ) {
1161- // FIXME #6573: is it sound to use the destination's repr on the base?
1162- // And, would it ever be reasonable to be here with discr != 0?
1163- let base_datum = unpack_datum ! ( bcx, trans_to_lvalue( bcx, & * base. expr, "base" ) ) ;
1164- for & ( i, t) in base. fields . iter ( ) {
1165- let datum = base_datum. get_element (
1166- t,
1167- |srcval| adt:: trans_field_ptr ( bcx, repr, srcval, discr, i) ) ;
1168- let dest = adt:: trans_field_ptr ( bcx, repr, addr, discr, i) ;
1169- bcx = datum. store_to ( bcx, dest) ;
1170- }
1171- }
1172-
1173- adt:: trans_set_discr ( bcx, repr, addr, discr) ;
1171+ adt:: trans_set_discr ( bcx, & * repr, addr, discr) ;
11741172
11751173 fcx. pop_custom_cleanup_scope ( custom_cleanup_scope) ;
11761174
1177- return bcx;
1175+ // If we don't care about the result drop the temporary we made
1176+ match dest {
1177+ SaveIn ( _) => bcx,
1178+ Ignore => {
1179+ bcx = glue:: drop_ty ( bcx, addr, ty) ;
1180+ base:: call_lifetime_end ( bcx, addr) ;
1181+ bcx
1182+ }
1183+ }
11781184}
11791185
11801186
0 commit comments