Skip to content

Commit 189a002

Browse files
committed
---
yaml --- r: 5314 b: refs/heads/master c: b843cf2 h: refs/heads/master v: v3
1 parent 1d528f1 commit 189a002

File tree

3 files changed

+50
-36
lines changed

3 files changed

+50
-36
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 29177864c353efd98182b02f5593e87183d184af
2+
refs/heads/master: b843cf2117d8be1317047d898d586c159b33a6f7

trunk/src/comp/middle/alias.rs

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
import syntax::{ast, ast_util};
33
import ast::{ident, fn_ident, node_id, def_id};
4-
import mut::{expr_root, mut_field, deref, field, index, unbox};
4+
import mut::{mut_field, deref, field, index, unbox};
55
import syntax::codemap::span;
66
import syntax::visit;
77
import visit::vt;
@@ -89,7 +89,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
8989
ast::expr_put(val) {
9090
alt val {
9191
some(ex) {
92-
let root = expr_root(cx.tcx, ex, false);
92+
let root = expr_root(*cx, ex, false);
9393
if mut_field(root.ds) {
9494
cx.tcx.sess.span_err(ex.span,
9595
"result of put must be" +
@@ -177,38 +177,13 @@ fn add_bindings_for_let(cx: ctx, &bs: [binding], loc: @ast::local) {
177177
cx.tcx.sess.span_err
178178
(loc.span, "can not move into a by-reference binding");
179179
}
180-
let root = expr_root(cx.tcx, init.expr, false);
181-
let outer_ds = *root.ds;
180+
let root = expr_root(cx, init.expr, false);
182181
let root_var = path_def_id(cx, root.ex);
183-
let is_temp = is_none(root_var);
184-
if is_temp {
185-
alt root.ex.node {
186-
ast::expr_call(f, args) {
187-
let fty = ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f));
188-
alt ty::ty_fn_ret_style(cx.tcx, fty) {
189-
ast::return_ref(mut, arg_n) {
190-
let arg = args[arg_n];
191-
let arg_root = expr_root(cx.tcx, arg, false);
192-
root_var = path_def_id(cx, arg_root.ex);
193-
if !is_none(root_var) {
194-
is_temp = false;
195-
if mut {
196-
outer_ds = [@{mut: true, kind: unbox,
197-
outer_t: ty::expr_ty(cx.tcx, arg)}];
198-
}
199-
outer_ds = *arg_root.ds + outer_ds;
200-
}
201-
}
202-
}
203-
}
204-
_ {}
205-
}
206-
}
207-
if is_temp {
182+
if is_none(root_var) {
208183
cx.tcx.sess.span_err(loc.span, "a reference binding can't be \
209184
rooted in a temporary");
210185
}
211-
for proot in *pattern_roots(cx.tcx, outer_ds, loc.node.pat) {
186+
for proot in *pattern_roots(cx.tcx, *root.ds, loc.node.pat) {
212187
let bnd = mk_binding(cx, proot.id, proot.span, root_var,
213188
inner_mut(proot.ds));
214189
// Don't implicitly copy explicit references
@@ -252,7 +227,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
252227
let i = 0u;
253228
for arg_t: ty::arg in arg_ts {
254229
let arg = args[i];
255-
let root = expr_root(cx.tcx, arg, false);
230+
let root = expr_root(cx, arg, false);
256231
if arg_t.mode == ast::by_mut_ref {
257232
alt path_def(cx, arg) {
258233
some(def) {
@@ -340,11 +315,13 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
340315

341316
fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
342317
expr: @ast::expr) {
343-
let root = expr_root(cx.tcx, expr, false);
318+
let root = expr_root(cx, expr, false);
344319
let bad = none;
345320
let mut_field = mut_field(root.ds);
346321
alt path_def(cx, root.ex) {
347-
none. { bad = some("a temporary"); }
322+
none. {
323+
bad = some("a temporary");
324+
}
348325
some(ast::def_local(did, _)) | some(ast::def_binding(did)) |
349326
some(ast::def_arg(did, _)) {
350327
let cur_node = did.node;
@@ -400,7 +377,7 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
400377
fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
401378
v: vt<scope>) {
402379
v.visit_expr(input, sc, v);
403-
let root = expr_root(cx.tcx, input, true);
380+
let root = expr_root(cx, input, true);
404381
for a: ast::arm in arms {
405382
let new_bs = sc.bs;
406383
let root_var = path_def_id(cx, root.ex);
@@ -448,7 +425,7 @@ fn check_for_each(cx: ctx, local: @ast::local, call: @ast::expr,
448425
fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
449426
sc: scope, v: vt<scope>) {
450427
v.visit_expr(seq, sc, v);
451-
let root = expr_root(cx.tcx, seq, false);
428+
let root = expr_root(cx, seq, false);
452429

453430
// If this is a mutable vector, don't allow it to be touched.
454431
let seq_t = ty::expr_ty(cx.tcx, seq);
@@ -695,6 +672,34 @@ fn pattern_roots(tcx: ty::ctxt, base: [deref], pat: @ast::pat)
695672
ret @set;
696673
}
697674

675+
// Wraps the expr_root in mut.rs to also handle roots that exist through
676+
// return-by-reference
677+
fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) ->
678+
{ex: @ast::expr, ds: @[deref]} {
679+
let base_root = mut::expr_root(cx.tcx, ex, autoderef);
680+
if is_none(path_def_id(cx, base_root.ex)) {
681+
alt base_root.ex.node {
682+
ast::expr_call(f, args) {
683+
let fty = ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f));
684+
alt ty::ty_fn_ret_style(cx.tcx, fty) {
685+
ast::return_ref(mut, arg_n) {
686+
let arg = args[arg_n];
687+
let arg_root = expr_root(cx, arg, false);
688+
ret {ex: arg_root.ex,
689+
ds: @(*arg_root.ds +
690+
(mut ? [@{mut: true, kind: unbox,
691+
outer_t: ty::expr_ty(cx.tcx, arg)}] : [])
692+
+ *base_root.ds)};
693+
}
694+
_ {}
695+
}
696+
}
697+
_ {}
698+
}
699+
}
700+
ret base_root;
701+
}
702+
698703
fn inner_mut(ds: @[deref]) -> [ty::t] {
699704
for d: deref in *ds { if d.mut { ret [d.outer_t]; } }
700705
ret [];

trunk/src/test/run-pass/ret-by-reference.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ fn get_mut(a: {mutable x: @int}, _b: int) -> &!0 @int {
1010
ret a.x;
1111
}
1212

13+
fn get_deep(a: {mutable y: {mutable x: @int}}) -> &!@int {
14+
ret get_mut(a.y, 1);
15+
}
16+
1317
fn main() {
1418
let x = some(@50);
1519
let &y = get(x);
@@ -20,4 +24,9 @@ fn main() {
2024
let &box = get_mut(y, 4);
2125
assert *box == 50;
2226
assert *get_mut({mutable x: @70}, 5) == 70;
27+
28+
let u = {mutable y: {mutable x: @10}};
29+
let &deep = get_deep(u);
30+
assert *deep == 10;
31+
assert *get_deep({mutable y: {mutable x: @11}}) + 2 == 13;
2332
}

0 commit comments

Comments
 (0)