Skip to content

Commit 180db08

Browse files
committed
Refactor expr_root in alias.rs
It was too clunky and specific before. Now returns a vec of dereference specs instead of a bunch of special-case information. Further accessors extract the information they need from this vec.
1 parent c5caff8 commit 180db08

File tree

1 file changed

+71
-73
lines changed

1 file changed

+71
-73
lines changed

src/comp/middle/alias.rs

Lines changed: 71 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ fn visit_expr(&@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
6464
alt (val) {
6565
case (some(?ex)) {
6666
auto root = expr_root(*cx, ex, false);
67-
if (!is_none(root.inner_mut)) {
67+
if (mut_field(root.ds)) {
6868
cx.tcx.sess.span_err
6969
(ex.span,
7070
"result of put must be immutably rooted");
@@ -129,7 +129,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
129129
vec::push(mut_roots, tup(i, did._1));
130130
}
131131
case (_) {
132-
if (!root.mut_field) {
132+
if (!mut_field(root.ds)) {
133133
cx.tcx.sess.span_err
134134
(arg.span, "passing a temporary value or \
135135
immutable field by mutable alias");
@@ -141,7 +141,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
141141
case (some(?did)) { vec::push(roots, did._1); }
142142
case (_) {}
143143
}
144-
alt (root.inner_mut) {
144+
alt (inner_mut(root.ds)) {
145145
case (some(?t)) {
146146
vec::push(unsafe_ts, t);
147147
vec::push(unsafe_t_offsets, i);
@@ -208,7 +208,7 @@ fn check_alt(&ctx cx, &@ast::expr input, &vec[ast::arm] arms,
208208
case (some(?did)) { [did._1] }
209209
case (_) { [] }
210210
};
211-
let vec[ty::t] forbidden_tp = alt (root.inner_mut) {
211+
let vec[ty::t] forbidden_tp = alt (inner_mut(root.ds)) {
212212
case (some(?t)) { [t] }
213213
case (_) { [] }
214214
};
@@ -276,7 +276,7 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq,
276276
case (some(?did)) { [did._1] }
277277
case (_) { [] }
278278
};
279-
auto unsafe = alt (root.inner_mut) {
279+
auto unsafe = alt (inner_mut(root.ds)) {
280280
case (some(?t)) { [t] }
281281
case (_) { [] }
282282
};
@@ -389,82 +389,89 @@ fn deps(&scope sc, vec[def_num] roots) -> vec[uint] {
389389
ret result;
390390
}
391391

392+
tag deref_t {
393+
unbox;
394+
field(ident);
395+
index;
396+
}
397+
type deref = rec(bool mut, deref_t kind, ty::t outer_t);
398+
399+
// Finds the root (the thing that is dereferenced) for the given expr, and a
400+
// vec of dereferences that were used on this root. Note that, in this vec,
401+
// the inner derefs come in front, so foo.bar.baz becomes rec(ex=foo,
402+
// ds=[field(baz),field(bar)])
392403
fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
393-
-> rec(@ast::expr ex,
394-
option::t[ty::t] inner_mut,
395-
bool mut_in_box,
396-
bool mut_field) {
397-
let option::t[ty::t] mut = none;
398-
// This is not currently used but would make it possible to be more
399-
// liberal -- only stuff in a mutable box needs full type-inclusion
400-
// checking, things that aren't in a box need only be checked against
401-
// locally live aliases and their root.
402-
auto mut_in_box = false;
403-
auto mut_fld = false;
404-
auto depth = 0;
404+
-> rec(@ast::expr ex, vec[deref] ds) {
405+
406+
fn maybe_auto_unbox(&ctx cx, &ty::t t)
407+
-> rec(ty::t t, option::t[deref] d) {
408+
alt (ty::struct(*cx.tcx, t)) {
409+
case (ty::ty_box(?mt)) {
410+
ret rec(t=mt.ty, d=some(rec(mut=mt.mut != ast::imm,
411+
kind=unbox,
412+
outer_t=t)));
413+
}
414+
case (_) {
415+
ret rec(t=t, d=none);
416+
}
417+
}
418+
}
419+
fn maybe_push_auto_unbox(&option::t[deref] d, &mutable vec[deref] ds) {
420+
alt (d) {
421+
case (some(?d)) { vec::push(ds, d); }
422+
case (none) {}
423+
}
424+
}
425+
426+
let vec[deref] ds = [];
405427
while (true) {
406428
alt ({ex.node}) {
407429
case (ast::expr_field(?base, ?ident, _)) {
408-
auto base_t = ty::expr_ty(*cx.tcx, base);
409-
auto auto_unbox = maybe_auto_unbox(cx, base_t);
430+
auto auto_unbox = maybe_auto_unbox
431+
(cx, ty::expr_ty(*cx.tcx, base));
432+
auto mut = false;
410433
alt (ty::struct(*cx.tcx, auto_unbox.t)) {
411434
case (ty::ty_tup(?fields)) {
412435
auto fnm = ty::field_num(cx.tcx.sess, ex.span, ident);
413-
if (fields.(fnm).mut != ast::imm) {
414-
if (is_none(mut)) { mut = some(auto_unbox.t); }
415-
if (depth == 0) { mut_fld = true; }
416-
}
436+
mut = fields.(fnm).mut != ast::imm;
417437
}
418438
case (ty::ty_rec(?fields)) {
419439
for (ty::field fld in fields) {
420440
if (str::eq(ident, fld.ident)) {
421-
if (fld.mt.mut != ast::imm) {
422-
if (is_none(mut)) {
423-
mut = some(auto_unbox.t);
424-
}
425-
if (depth == 0) { mut_fld = true; }
426-
}
441+
mut = fld.mt.mut != ast::imm;
427442
break;
428443
}
429444
}
430445
}
431446
case (ty::ty_obj(_)) {}
432447
}
433-
if (auto_unbox.done) {
434-
if (!is_none(mut)) { mut_in_box = true; }
435-
else if (auto_unbox.mut) { mut = some(base_t); }
436-
}
448+
vec::push(ds, rec(mut=mut,
449+
kind=field(ident),
450+
outer_t=auto_unbox.t));
451+
maybe_push_auto_unbox(auto_unbox.d, ds);
437452
ex = base;
438453
}
439454
case (ast::expr_index(?base, _, _)) {
440-
auto base_t = ty::expr_ty(*cx.tcx, base);
441-
auto auto_unbox = maybe_auto_unbox(cx, base_t);
455+
auto auto_unbox = maybe_auto_unbox
456+
(cx, ty::expr_ty(*cx.tcx, base));
442457
alt (ty::struct(*cx.tcx, auto_unbox.t)) {
443458
case (ty::ty_vec(?mt)) {
444-
if (mt.mut != ast::imm) {
445-
if (is_none(mut)) { mut = some(auto_unbox.t); }
446-
if (depth == 0) { mut_fld = true; }
447-
}
459+
vec::push(ds, rec(mut=mt.mut != ast::imm,
460+
kind=index,
461+
outer_t=auto_unbox.t));
448462
}
449463
}
450-
if (auto_unbox.done) {
451-
if (!is_none(mut)) { mut_in_box = true; }
452-
else if (auto_unbox.mut) { mut = some(base_t); }
453-
}
464+
maybe_push_auto_unbox(auto_unbox.d, ds);
454465
ex = base;
455466
}
456467
case (ast::expr_unary(?op, ?base, _)) {
457468
if (op == ast::deref) {
458469
auto base_t = ty::expr_ty(*cx.tcx, base);
459470
alt (ty::struct(*cx.tcx, base_t)) {
460471
case (ty::ty_box(?mt)) {
461-
if (mt.mut != ast::imm) {
462-
if (is_none(mut)) { mut = some(base_t); }
463-
if (depth == 0) { mut_fld = true; }
464-
}
465-
if (!is_none(mut)) {
466-
mut_in_box = true;
467-
}
472+
vec::push(ds, rec(mut=mt.mut != ast::imm,
473+
kind=unbox,
474+
outer_t=base_t));
468475
}
469476
}
470477
ex = base;
@@ -474,35 +481,26 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
474481
}
475482
case (_) { break; }
476483
}
477-
depth += 1;
478484
}
479485
if (autoderef) {
480-
auto ex_t = ty::expr_ty(*cx.tcx, ex);
481-
auto auto_unbox = maybe_auto_unbox(cx, ex_t);
482-
if (auto_unbox.done) {
483-
if (!is_none(mut)) { mut_in_box = true; }
484-
else if (auto_unbox.mut) {
485-
mut = some(ex_t);
486-
if (depth == 0) { mut_fld = true; }
487-
}
488-
}
486+
auto auto_unbox = maybe_auto_unbox(cx, ty::expr_ty(*cx.tcx, ex));
487+
maybe_push_auto_unbox(auto_unbox.d, ds);
489488
}
490-
ret rec(ex = ex,
491-
inner_mut = mut,
492-
mut_in_box = mut_in_box,
493-
mut_field = mut_fld);
489+
ret rec(ex=ex, ds=ds);
494490
}
495491

496-
fn maybe_auto_unbox(&ctx cx, &ty::t t)
497-
-> rec(ty::t t, bool done, bool mut) {
498-
alt (ty::struct(*cx.tcx, t)) {
499-
case (ty::ty_box(?mt)) {
500-
ret rec(t=mt.ty, done=true, mut=mt.mut != ast::imm);
501-
}
502-
case (_) {
503-
ret rec(t=t, done=false, mut=false);
504-
}
492+
fn mut_field(&vec[deref] ds) -> bool {
493+
for (deref d in ds) {
494+
if (d.mut) { ret true; }
495+
}
496+
ret false;
497+
}
498+
499+
fn inner_mut(&vec[deref] ds) -> option::t[ty::t] {
500+
for (deref d in ds) {
501+
if (d.mut) { ret some(d.outer_t); }
505502
}
503+
ret none;
506504
}
507505

508506
fn path_def_id(&ctx cx, &@ast::expr ex) -> option::t[ast::def_id] {

0 commit comments

Comments
 (0)