@@ -3207,6 +3207,25 @@ fn trans_callee(cx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
3207
3207
}
3208
3208
}
3209
3209
3210
+ fn expr_is_lval ( tcx : ty:: ctxt , e : @ast:: expr ) -> bool {
3211
+ alt e. node {
3212
+ ast:: expr_path ( _) | ast:: expr_index ( _, _) |
3213
+ ast:: expr_unary ( ast:: deref. , _) { true }
3214
+ ast:: expr_field ( base, ident) {
3215
+ let basety = ty:: type_autoderef ( tcx, ty:: expr_ty ( tcx, base) ) ;
3216
+ alt ty:: struct ( tcx, basety) {
3217
+ ty:: ty_obj ( _) { false }
3218
+ ty:: ty_rec ( _) { true }
3219
+ }
3220
+ }
3221
+ ast:: expr_call ( f, _) {
3222
+ let fty = ty:: expr_ty ( tcx, f) ;
3223
+ ast_util:: ret_by_ref ( ty:: ty_fn_ret_style ( tcx, fty) )
3224
+ }
3225
+ _ { false }
3226
+ }
3227
+ }
3228
+
3210
3229
// The additional bool returned indicates whether it's mem (that is
3211
3230
// represented as an alloca or heap, hence needs a 'load' to be used as an
3212
3231
// immediate).
@@ -4149,20 +4168,6 @@ fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result {
4149
4168
add_clean_temp ( bcx, r. val , e_ty) ;
4150
4169
ret r;
4151
4170
}
4152
- ast:: expr_move ( dst, src) {
4153
- let lhs_res = trans_lval ( cx, dst) ;
4154
- assert ( lhs_res. is_mem ) ;
4155
- // FIXME Fill in lhs_res.bcx.sp
4156
-
4157
- let rhs_res = trans_lval ( lhs_res. bcx , src) ;
4158
- let t = ty:: expr_ty ( bcx_tcx ( cx) , src) ;
4159
- // FIXME: calculate copy init-ness in typestate.
4160
-
4161
- let bcx =
4162
- move_val ( rhs_res. bcx , DROP_EXISTING , lhs_res. val , rhs_res,
4163
- t) ;
4164
- ret rslt( bcx, C_nil ( ) ) ;
4165
- }
4166
4171
ast:: expr_bind ( f, args) { ret trans_bind ( cx, f, args, e. id ) ; }
4167
4172
ast:: expr_cast ( val, _) { ret trans_cast ( cx, val, e. id ) ; }
4168
4173
ast:: expr_anon_obj ( anon_obj) {
@@ -4325,6 +4330,19 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
4325
4330
assert is_mem;
4326
4331
ret trans_expr_save_in ( bcx, src, lhs_addr, DROP_EXISTING ) ;
4327
4332
}
4333
+ ast:: expr_move ( dst, src) {
4334
+ assert dest == ignore;
4335
+ let { bcx, val: addr , is_mem } = trans_lval ( bcx, dst) ;
4336
+ assert is_mem;
4337
+ // FIXME: calculate copy init-ness in typestate.
4338
+ if expr_is_lval ( bcx_tcx ( bcx) , src) {
4339
+ ret trans_expr_save_in ( bcx, src, addr, DROP_EXISTING ) ;
4340
+ } else {
4341
+ let srclv = trans_lval ( bcx, src) ;
4342
+ let t = ty:: expr_ty ( bcx_tcx ( bcx) , src) ;
4343
+ ret move_val( srclv. bcx , DROP_EXISTING , addr, srclv, t) ;
4344
+ }
4345
+ }
4328
4346
ast:: expr_swap ( dst, src) {
4329
4347
assert dest == ignore;
4330
4348
let lhs_res = trans_lval ( bcx, dst) ;
@@ -4665,15 +4683,12 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
4665
4683
4666
4684
alt local. node . init {
4667
4685
some ( init) {
4668
- alt init. op {
4669
- ast :: init_assign . {
4686
+ if init. op == ast :: init_assign ||
4687
+ ! expr_is_lval ( bcx_tcx ( bcx ) , init . expr ) {
4670
4688
bcx = trans_expr_save_in ( bcx, init. expr , llptr, INIT ) ;
4671
- }
4672
- // FIXME[DPS] do a save_in when expr isn't lval
4673
- ast:: init_move. {
4689
+ } else { // This is a move from an lval, must perform an actual move
4674
4690
let sub = trans_lval ( bcx, init. expr ) ;
4675
4691
bcx = move_val ( sub. bcx , INIT , llptr, sub, ty) ;
4676
- }
4677
4692
}
4678
4693
}
4679
4694
_ { bcx = zero_alloca ( bcx, llptr, ty) ; }
0 commit comments