|
1 | 1 |
|
2 | 2 | import syntax::{ast, ast_util};
|
3 | 3 | 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}; |
5 | 5 | import syntax::codemap::span;
|
6 | 6 | import syntax::visit;
|
7 | 7 | import visit::vt;
|
@@ -89,7 +89,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
|
89 | 89 | ast::expr_put(val) {
|
90 | 90 | alt val {
|
91 | 91 | some(ex) {
|
92 |
| - let root = expr_root(cx.tcx, ex, false); |
| 92 | + let root = expr_root(*cx, ex, false); |
93 | 93 | if mut_field(root.ds) {
|
94 | 94 | cx.tcx.sess.span_err(ex.span,
|
95 | 95 | "result of put must be" +
|
@@ -177,38 +177,13 @@ fn add_bindings_for_let(cx: ctx, &bs: [binding], loc: @ast::local) {
|
177 | 177 | cx.tcx.sess.span_err
|
178 | 178 | (loc.span, "can not move into a by-reference binding");
|
179 | 179 | }
|
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); |
182 | 181 | 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) { |
208 | 183 | cx.tcx.sess.span_err(loc.span, "a reference binding can't be \
|
209 | 184 | rooted in a temporary");
|
210 | 185 | }
|
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) { |
212 | 187 | let bnd = mk_binding(cx, proot.id, proot.span, root_var,
|
213 | 188 | inner_mut(proot.ds));
|
214 | 189 | // Don't implicitly copy explicit references
|
@@ -252,7 +227,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
|
252 | 227 | let i = 0u;
|
253 | 228 | for arg_t: ty::arg in arg_ts {
|
254 | 229 | let arg = args[i];
|
255 |
| - let root = expr_root(cx.tcx, arg, false); |
| 230 | + let root = expr_root(cx, arg, false); |
256 | 231 | if arg_t.mode == ast::by_mut_ref {
|
257 | 232 | alt path_def(cx, arg) {
|
258 | 233 | some(def) {
|
@@ -340,11 +315,13 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
|
340 | 315 |
|
341 | 316 | fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
|
342 | 317 | expr: @ast::expr) {
|
343 |
| - let root = expr_root(cx.tcx, expr, false); |
| 318 | + let root = expr_root(cx, expr, false); |
344 | 319 | let bad = none;
|
345 | 320 | let mut_field = mut_field(root.ds);
|
346 | 321 | alt path_def(cx, root.ex) {
|
347 |
| - none. { bad = some("a temporary"); } |
| 322 | + none. { |
| 323 | + bad = some("a temporary"); |
| 324 | + } |
348 | 325 | some(ast::def_local(did, _)) | some(ast::def_binding(did)) |
|
349 | 326 | some(ast::def_arg(did, _)) {
|
350 | 327 | let cur_node = did.node;
|
@@ -400,7 +377,7 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
|
400 | 377 | fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
|
401 | 378 | v: vt<scope>) {
|
402 | 379 | v.visit_expr(input, sc, v);
|
403 |
| - let root = expr_root(cx.tcx, input, true); |
| 380 | + let root = expr_root(cx, input, true); |
404 | 381 | for a: ast::arm in arms {
|
405 | 382 | let new_bs = sc.bs;
|
406 | 383 | 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,
|
448 | 425 | fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
|
449 | 426 | sc: scope, v: vt<scope>) {
|
450 | 427 | v.visit_expr(seq, sc, v);
|
451 |
| - let root = expr_root(cx.tcx, seq, false); |
| 428 | + let root = expr_root(cx, seq, false); |
452 | 429 |
|
453 | 430 | // If this is a mutable vector, don't allow it to be touched.
|
454 | 431 | let seq_t = ty::expr_ty(cx.tcx, seq);
|
@@ -695,6 +672,34 @@ fn pattern_roots(tcx: ty::ctxt, base: [deref], pat: @ast::pat)
|
695 | 672 | ret @set;
|
696 | 673 | }
|
697 | 674 |
|
| 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 | + |
698 | 703 | fn inner_mut(ds: @[deref]) -> [ty::t] {
|
699 | 704 | for d: deref in *ds { if d.mut { ret [d.outer_t]; } }
|
700 | 705 | ret [];
|
|
0 commit comments