Skip to content

Commit 2c917a6

Browse files
committed
---
yaml --- r: 5310 b: refs/heads/master c: 87fa389 h: refs/heads/master v: v3
1 parent e9fb01c commit 2c917a6

File tree

4 files changed

+48
-40
lines changed

4 files changed

+48
-40
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 25787bd2b887edcd7749268b6d0d1376312714d1
2+
refs/heads/master: 87fa38910eb78c116cd34b2524edd9c1cfe97228

trunk/src/comp/middle/alias.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,35 @@ fn add_bindings_for_let(cx: ctx, &bs: [binding], loc: @ast::local) {
182182
(loc.span, "can not move into a by-reference binding");
183183
}
184184
let root = expr_root(cx.tcx, init.expr, false);
185+
let outer_ds = *root.ds;
185186
let root_var = path_def_id(cx, root.ex);
186-
// FIXME also allow by-ref function calls
187-
if is_none(root_var) {
187+
let is_temp = is_none(root_var);
188+
if is_temp {
189+
alt root.ex.node {
190+
ast::expr_call(f, args) {
191+
let fty = ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f));
192+
let ret_style = ty::ty_fn_ret_style(cx.tcx, fty);
193+
if ast_util::ret_by_ref(ret_style) {
194+
// FIXME pick right arg
195+
let arg_root = expr_root(cx.tcx, args[0], false);
196+
root_var = path_def_id(cx, arg_root.ex);
197+
if !is_none(root_var) {
198+
is_temp = false;
199+
if ret_style == ast::return_ref(true) {
200+
outer_ds = [@{mut: true with *arg_root.ds[0]}];
201+
}
202+
outer_ds = *arg_root.ds + outer_ds;
203+
}
204+
}
205+
}
206+
_ {}
207+
}
208+
}
209+
if is_temp {
188210
cx.tcx.sess.span_err(loc.span, "a reference binding can't be \
189211
rooted in a temporary");
190212
}
191-
for proot in *pattern_roots(cx.tcx, *root.ds, loc.node.pat) {
213+
for proot in *pattern_roots(cx.tcx, outer_ds, loc.node.pat) {
192214
let bnd = mk_binding(cx, proot.id, proot.span, root_var,
193215
inner_mut(proot.ds));
194216
// Don't implicitly copy explicit references

trunk/src/comp/middle/trans.rs

+22-25
Original file line numberDiff line numberDiff line change
@@ -2731,7 +2731,7 @@ fn trans_for_each(cx: @block_ctxt, local: @ast::local, seq: @ast::expr,
27312731
ast::expr_call(f, args) {
27322732
let pair =
27332733
create_real_fn_pair(cx, iter_body_llty, lliterbody, llenv.ptr);
2734-
r = trans_call(cx, f, some(pair), args, seq.id);
2734+
r = trans_call(cx, f, some(pair), args, seq.id).res;
27352735
ret rslt(r.bcx, C_nil());
27362736
}
27372737
}
@@ -3089,6 +3089,12 @@ fn trans_lval_gen(cx: @block_ctxt, e: @ast::expr) -> lval_result {
30893089
}
30903090
}
30913091
}
3092+
ast::expr_call(f, args) {
3093+
let {res: {bcx, val}, by_ref} =
3094+
trans_call(cx, f, none, args, e.id);
3095+
if by_ref { ret lval_mem(bcx, val); }
3096+
else { ret lval_val(bcx, val); }
3097+
}
30923098
_ {
30933099
ret {res: trans_expr(cx, e),
30943100
is_mem: false,
@@ -3623,7 +3629,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
36233629

36243630
fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
36253631
lliterbody: option::t<ValueRef>, args: [@ast::expr],
3626-
id: ast::node_id) -> result {
3632+
id: ast::node_id) -> {res: result, by_ref: bool} {
36273633
// NB: 'f' isn't necessarily a function; it might be an entire self-call
36283634
// expression because of the hack that allows us to process self-calls
36293635
// with trans_call.
@@ -3690,8 +3696,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
36903696
none. {
36913697
if !ty::type_is_nil(bcx_tcx(cx), ret_ty) {
36923698
if by_ref {
3693-
let retptr = Load(bcx, llretslot);
3694-
retval = load_if_immediate(bcx, retptr, ret_ty);
3699+
retval = Load(bcx, llretslot);
36953700
} else {
36963701
retval = load_if_immediate(bcx, llretslot, ret_ty);
36973702
// Retval doesn't correspond to anything really tangible
@@ -3720,7 +3725,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
37203725
Br(bcx, next_cx.llbb);
37213726
bcx = next_cx;
37223727
}
3723-
ret rslt(bcx, retval);
3728+
ret {res: rslt(bcx, retval), by_ref: by_ref};
37243729
}
37253730

37263731
fn invoke(bcx: @block_ctxt, llfn: ValueRef,
@@ -3887,9 +3892,6 @@ fn trans_expr_out(cx: @block_ctxt, e: @ast::expr, output: out_method) ->
38873892
// Fixme Fill in cx.sp
38883893
alt e.node {
38893894
ast::expr_lit(lit) { ret trans_lit(cx, *lit); }
3890-
ast::expr_unary(op, x) {
3891-
if op != ast::deref { ret trans_unary(cx, op, x, e.id); }
3892-
}
38933895
ast::expr_binary(op, x, y) { ret trans_binary(cx, op, x, y); }
38943896
ast::expr_if(cond, thn, els) {
38953897
ret with_out_method(bind trans_if(cx, cond, thn, els, _), cx, e.id,
@@ -4044,9 +4046,6 @@ fn trans_expr_out(cx: @block_ctxt, e: @ast::expr, output: out_method) ->
40444046
ret rslt(bcx, C_nil());
40454047
}
40464048
ast::expr_bind(f, args) { ret trans_bind(cx, f, args, e.id); }
4047-
ast::expr_call(f, args) {
4048-
ret trans_call(cx, f, none::<ValueRef>, args, e.id);
4049-
}
40504049
ast::expr_cast(val, _) { ret trans_cast(cx, val, e.id); }
40514050
ast::expr_vec(args, _) { ret tvec::trans_vec(cx, args, e.id); }
40524051
ast::expr_rec(args, base) { ret trans_rec(cx, args, base, e.id); }
@@ -4092,21 +4091,18 @@ fn trans_expr_out(cx: @block_ctxt, e: @ast::expr, output: out_method) ->
40924091
ast::expr_anon_obj(anon_obj) {
40934092
ret trans_anon_obj(cx, e.span, anon_obj, e.id);
40944093
}
4095-
_ {
4096-
// The expression is an lvalue. Fall through.
4097-
assert (ty::is_lval(e));
4098-
// make sure it really is and that we
4099-
// didn't forget to add a case for a new expr!
4094+
ast::expr_call(_, _) | ast::expr_field(_, _) | ast::expr_index(_, _) |
4095+
ast::expr_path(_) | ast::expr_unary(ast::deref., _) {
4096+
let t = ty::expr_ty(bcx_tcx(cx), e);
4097+
let sub = trans_lval(cx, e);
4098+
let v = sub.res.val;
4099+
if sub.is_mem { v = load_if_immediate(sub.res.bcx, v, t); }
4100+
ret rslt(sub.res.bcx, v);
4101+
}
4102+
ast::expr_unary(op, x) {
4103+
ret trans_unary(cx, op, x, e.id);
41004104
}
41014105
}
4102-
// lval cases fall through to trans_lval and then
4103-
// possibly load the result (if it's non-structural).
4104-
4105-
let t = ty::expr_ty(bcx_tcx(cx), e);
4106-
let sub = trans_lval(cx, e);
4107-
let v = sub.res.val;
4108-
if sub.is_mem { v = load_if_immediate(sub.res.bcx, v, t); }
4109-
ret rslt(sub.res.bcx, v);
41104106
}
41114107

41124108
fn with_out_method(work: fn(out_method) -> result, cx: @block_ctxt,
@@ -4517,7 +4513,8 @@ fn init_ref_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
45174513
let init_expr = option::get(local.node.init).expr;
45184514
let val = trans_lval(bcx, init_expr);
45194515
assert val.is_mem;
4520-
ret trans_alt::bind_irrefutable_pat(bcx, local.node.pat, val.res.val,
4516+
ret trans_alt::bind_irrefutable_pat(val.res.bcx, local.node.pat,
4517+
val.res.val,
45214518
bcx.fcx.lllocals, false);
45224519
}
45234520

trunk/src/comp/middle/ty.rs

-11
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ export fm_general;
5050
export get_element_type;
5151
export hash_ty;
5252
export idx_nil;
53-
export is_lval;
5453
export is_binopable;
5554
export is_pred_ty;
5655
export lookup_item_type;
@@ -1713,16 +1712,6 @@ fn sort_methods(meths: [method]) -> [method] {
17131712
ret std::sort::merge_sort::<method>(bind method_lteq(_, _), meths);
17141713
}
17151714

1716-
fn is_lval(expr: @ast::expr) -> bool {
1717-
alt expr.node {
1718-
ast::expr_field(_, _) { ret true; }
1719-
ast::expr_index(_, _) { ret true; }
1720-
ast::expr_path(_) { ret true; }
1721-
ast::expr_unary(ast::deref., _) { ret true; }
1722-
_ { ret false; }
1723-
}
1724-
}
1725-
17261715
fn occurs_check_fails(tcx: ctxt, sp: option::t<span>, vid: int, rt: t) ->
17271716
bool {
17281717
if !type_contains_vars(tcx, rt) {

0 commit comments

Comments
 (0)