Skip to content

Commit 04cb637

Browse files
committed
---
yaml --- r: 5331 b: refs/heads/master c: fb42d83 h: refs/heads/master i: 5329: 22b702a 5327: 24d73ea v: v3
1 parent 49f4117 commit 04cb637

File tree

3 files changed

+65
-71
lines changed

3 files changed

+65
-71
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: d7587c1eda9b46b57b77585638fd775490ff836e
2+
refs/heads/master: fb42d839a0552d65433012fc48dbc6214c07bcdb

trunk/src/comp/middle/alias.rs

Lines changed: 64 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11

22
import syntax::{ast, ast_util};
33
import ast::{ident, fn_ident, node_id, def_id};
4-
import mut::{mut_field, deref, field, index, unbox};
54
import syntax::codemap::span;
65
import syntax::visit;
76
import visit::vt;
@@ -15,11 +14,13 @@ import std::option::{some, none, is_none};
1514
tag valid { valid; overwritten(span, ast::path); val_taken(span, ast::path); }
1615
tag copied { not_allowed; copied; not_copied; }
1716

17+
tag unsafe_ty { contains(ty::t); mut_contains(ty::t); }
18+
1819
type binding = @{node_id: node_id,
1920
span: span,
2021
root_var: option::t<node_id>,
2122
local_id: uint,
22-
unsafe_tys: [ty::t],
23+
unsafe_tys: [unsafe_ty],
2324
mutable ok: valid,
2425
mutable copied: copied};
2526

@@ -28,7 +29,7 @@ tag ret_info { by_ref(bool, node_id); other; }
2829
type scope = {bs: [binding], ret_info: ret_info};
2930

3031
fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option::t<node_id>,
31-
unsafe: [ty::t]) -> binding {
32+
unsafe: [unsafe_ty]) -> binding {
3233
ret @{node_id: id, span: span, root_var: root_var,
3334
local_id: local_id_of_node(cx, id),
3435
unsafe_tys: unsafe, mutable ok: valid,
@@ -92,7 +93,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
9293
alt val {
9394
some(ex) {
9495
let root = expr_root(*cx, ex, false);
95-
if mut_field(root.ds) {
96+
if !is_none(root.mut) {
9697
cx.tcx.sess.span_err(ex.span,
9798
"result of put must be" +
9899
" immutably rooted");
@@ -185,9 +186,9 @@ fn add_bindings_for_let(cx: ctx, &bs: [binding], loc: @ast::local) {
185186
cx.tcx.sess.span_err(loc.span, "a reference binding can't be \
186187
rooted in a temporary");
187188
}
188-
for proot in *pattern_roots(cx.tcx, *root.ds, loc.node.pat) {
189+
for proot in pattern_roots(cx.tcx, root.mut, loc.node.pat) {
189190
let bnd = mk_binding(cx, proot.id, proot.span, root_var,
190-
inner_mut(proot.ds));
191+
unsafe_set(proot.mut));
191192
// Don't implicitly copy explicit references
192193
bnd.copied = not_allowed;
193194
bs += [bnd];
@@ -246,7 +247,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
246247
span: arg.span,
247248
root_var: root_var,
248249
local_id: 0u,
249-
unsafe_tys: inner_mut(root.ds),
250+
unsafe_tys: unsafe_set(root.mut),
250251
mutable ok: valid,
251252
mutable copied: alt arg_t.mode {
252253
ast::by_move. { copied }
@@ -276,12 +277,13 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
276277
}
277278
let j = 0u;
278279
for b in bindings {
279-
for ty in b.unsafe_tys {
280+
for unsafe in b.unsafe_tys {
280281
let i = 0u;
281282
for arg_t: ty::arg in arg_ts {
282283
let mut_alias = arg_t.mode == ast::by_mut_ref;
283284
if i != j &&
284-
ty_can_unsafely_include(cx, ty, arg_t.ty, mut_alias) &&
285+
ty_can_unsafely_include(cx, unsafe, arg_t.ty,
286+
mut_alias) &&
285287
cant_copy(cx, b) {
286288
cx.tcx.sess.span_err
287289
(args[i].span,
@@ -323,7 +325,7 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
323325
expr: @ast::expr) {
324326
let root = expr_root(cx, expr, false);
325327
let bad = none;
326-
let mut_field = mut_field(root.ds);
328+
let mut_field = !is_none(root.mut);
327329
alt path_def(cx, root.ex) {
328330
none. {
329331
bad = some("a temporary");
@@ -388,18 +390,18 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
388390
let new_bs = sc.bs;
389391
let root_var = path_def_id(cx, root.ex);
390392
let pat_id_map = ast_util::pat_id_map(a.pats[0]);
391-
type info = {id: node_id, mutable unsafe: [ty::t], span: span};
393+
type info = {id: node_id, mutable unsafe: [unsafe_ty], span: span};
392394
let binding_info: [info] = [];
393395
for pat in a.pats {
394-
for proot in *pattern_roots(cx.tcx, *root.ds, pat) {
396+
for proot in pattern_roots(cx.tcx, root.mut, pat) {
395397
let canon_id = pat_id_map.get(proot.name);
396398
// FIXME I wanted to use a block here, but that hit bug #913
397399
fn match(x: info, canon: node_id) -> bool { x.id == canon }
398400
alt vec::find(bind match(_, canon_id), binding_info) {
399-
some(s) { s.unsafe += inner_mut(proot.ds); }
401+
some(s) { s.unsafe += unsafe_set(proot.mut); }
400402
none. {
401403
binding_info += [{id: canon_id,
402-
mutable unsafe: inner_mut(proot.ds),
404+
mutable unsafe: unsafe_set(proot.mut),
403405
span: proot.span}];
404406
}
405407
}
@@ -419,9 +421,9 @@ fn check_for_each(cx: ctx, local: @ast::local, call: @ast::expr,
419421
alt call.node {
420422
ast::expr_call(f, args) {
421423
let new_bs = sc.bs + check_call(cx, f, args);
422-
for proot in *pattern_roots(cx.tcx, [], local.node.pat) {
424+
for proot in pattern_roots(cx.tcx, none, local.node.pat) {
423425
new_bs += [mk_binding(cx, proot.id, proot.span, none,
424-
inner_mut(proot.ds))];
426+
unsafe_set(proot.mut))];
425427
}
426428
visit::visit_block(blk, {bs: new_bs with sc}, v);
427429
}
@@ -435,20 +437,20 @@ fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
435437

436438
// If this is a mutable vector, don't allow it to be touched.
437439
let seq_t = ty::expr_ty(cx.tcx, seq);
438-
let ext_ds = *root.ds;
440+
let cur_mut = root.mut;
439441
alt ty::struct(cx.tcx, seq_t) {
440442
ty::ty_vec(mt) {
441443
if mt.mut != ast::imm {
442-
ext_ds += [@{mut: true, kind: index, outer_t: seq_t}];
444+
cur_mut = some(contains(seq_t));
443445
}
444446
}
445447
_ {}
446448
}
447449
let root_var = path_def_id(cx, root.ex);
448450
let new_bs = sc.bs;
449-
for proot in *pattern_roots(cx.tcx, ext_ds, local.node.pat) {
451+
for proot in pattern_roots(cx.tcx, cur_mut, local.node.pat) {
450452
new_bs += [mk_binding(cx, proot.id, proot.span, root_var,
451-
inner_mut(proot.ds))];
453+
unsafe_set(proot.mut))];
452454
}
453455
visit::visit_block(blk, {bs: new_bs with sc}, v);
454456
}
@@ -463,8 +465,8 @@ fn check_var(cx: ctx, ex: @ast::expr, p: ast::path, id: ast::node_id,
463465
for b in sc.bs {
464466
// excludes variables introduced since the alias was made
465467
if my_local_id < b.local_id {
466-
for ty in b.unsafe_tys {
467-
if ty_can_unsafely_include(cx, ty, var_t, assign) {
468+
for unsafe in b.unsafe_tys {
469+
if ty_can_unsafely_include(cx, unsafe, var_t, assign) {
468470
b.ok = val_taken(ex.span, p);
469471
}
470472
}
@@ -539,14 +541,17 @@ fn path_def_id(cx: ctx, ex: @ast::expr) -> option::t<ast::node_id> {
539541
}
540542
}
541543

542-
fn ty_can_unsafely_include(cx: ctx, needle: ty::t, haystack: ty::t, mut: bool)
543-
-> bool {
544+
fn ty_can_unsafely_include(cx: ctx, needle: unsafe_ty, haystack: ty::t,
545+
mut: bool) -> bool {
544546
fn get_mut(cur: bool, mt: ty::mt) -> bool {
545547
ret cur || mt.mut != ast::imm;
546548
}
547-
fn helper(tcx: ty::ctxt, needle: ty::t, haystack: ty::t, mut: bool) ->
548-
bool {
549-
if needle == haystack { ret true; }
549+
fn helper(tcx: ty::ctxt, needle: unsafe_ty, haystack: ty::t, mut: bool)
550+
-> bool {
551+
if alt needle {
552+
contains(ty) { ty == haystack }
553+
mut_contains(ty) { mut && ty == haystack }
554+
} { ret true; }
550555
alt ty::struct(tcx, haystack) {
551556
ty::ty_tag(_, ts) {
552557
for t: ty::t in ts {
@@ -570,23 +575,13 @@ fn ty_can_unsafely_include(cx: ctx, needle: ty::t, haystack: ty::t, mut: bool)
570575
for t in ts { if helper(tcx, needle, t, mut) { ret true; } }
571576
ret false;
572577
}
573-
574-
575-
576-
577-
578578
// These may contain anything.
579-
ty::ty_fn(_, _, _, _, _) {
580-
ret true;
581-
}
582-
ty::ty_obj(_) { ret true; }
579+
ty::ty_fn(_, _, _, _, _) | ty::ty_obj(_) { ret true; }
583580
// A type param may include everything, but can only be
584581
// treated as opaque downstream, and is thus safe unless we
585582
// saw mutable fields, in which case the whole thing can be
586583
// overwritten.
587-
ty::ty_param(_, _) {
588-
ret mut;
589-
}
584+
ty::ty_param(_, _) { ret mut; }
590585
_ { ret false; }
591586
}
592587
}
@@ -640,49 +635,53 @@ fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool {
640635
ret score_ty(tcx, ty) > 8u;
641636
}
642637

643-
type pattern_root = {id: node_id, name: ident, ds: @[deref], span: span};
638+
type pattern_root = {id: node_id,
639+
name: ident,
640+
mut: option::t<unsafe_ty>,
641+
span: span};
644642

645-
fn pattern_roots(tcx: ty::ctxt, base: [deref], pat: @ast::pat)
646-
-> @[pattern_root] {
647-
fn walk(tcx: ty::ctxt, base: [deref], pat: @ast::pat,
643+
fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
644+
-> [pattern_root] {
645+
fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
648646
&set: [pattern_root]) {
649647
alt pat.node {
650648
ast::pat_wild. | ast::pat_lit(_) {}
651649
ast::pat_bind(nm) {
652-
set += [{id: pat.id, name: nm, ds: @base, span: pat.span}];
650+
set += [{id: pat.id, name: nm, mut: mut, span: pat.span}];
653651
}
654652
ast::pat_tag(_, ps) | ast::pat_tup(ps) {
655-
let base = base + [@{mut: false, kind: field,
656-
outer_t: ty::node_id_to_type(tcx, pat.id)}];
657-
for p in ps { walk(tcx, base, p, set); }
653+
for p in ps { walk(tcx, mut, p, set); }
658654
}
659655
ast::pat_rec(fs, _) {
660656
let ty = ty::node_id_to_type(tcx, pat.id);
661657
for f in fs {
662-
let mut = ty::get_field(tcx, ty, f.ident).mt.mut != ast::imm;
663-
let base = base + [@{mut: mut, kind: field, outer_t: ty}];
664-
walk(tcx, base, f.pat, set);
658+
let m = ty::get_field(tcx, ty, f.ident).mt.mut != ast::imm;
659+
walk(tcx, m ? some(contains(ty)) : mut, f.pat, set);
665660
}
666661
}
667662
ast::pat_box(p) {
668663
let ty = ty::node_id_to_type(tcx, pat.id);
669-
let mut = alt ty::struct(tcx, ty) {
664+
let m = alt ty::struct(tcx, ty) {
670665
ty::ty_box(mt) { mt.mut != ast::imm }
671666
};
672-
walk(tcx, base + [@{mut: mut, kind: unbox, outer_t: ty}], p, set);
667+
walk(tcx, m ? some(contains(ty)) : mut, p, set);
673668
}
674669
}
675670
}
676671
let set = [];
677-
walk(tcx, base, pat, set);
678-
ret @set;
672+
walk(tcx, mut, pat, set);
673+
ret set;
679674
}
680675

681676
// Wraps the expr_root in mut.rs to also handle roots that exist through
682677
// return-by-reference
683-
fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) ->
684-
{ex: @ast::expr, ds: @[deref]} {
678+
fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool)
679+
-> {ex: @ast::expr, mut: option::t<unsafe_ty>} {
685680
let base_root = mut::expr_root(cx.tcx, ex, autoderef);
681+
let unsafe = none;
682+
for d in *base_root.ds {
683+
if d.mut { unsafe = some(contains(d.outer_t)); break; }
684+
}
686685
if is_none(path_def_id(cx, base_root.ex)) {
687686
alt base_root.ex.node {
688687
ast::expr_call(f, args) {
@@ -691,24 +690,24 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) ->
691690
ast::return_ref(mut, arg_n) {
692691
let arg = args[arg_n - 1u];
693692
let arg_root = expr_root(cx, arg, false);
694-
ret {ex: arg_root.ex,
695-
ds: @(*arg_root.ds +
696-
(mut ? [@{mut: true, kind: unbox,
697-
outer_t: ty::expr_ty(cx.tcx, arg)}] : [])
698-
+ *base_root.ds)};
693+
if mut {
694+
let ret_ty = ty::expr_ty(cx.tcx, base_root.ex);
695+
unsafe = some(mut_contains(ret_ty));
696+
}
697+
if !is_none(arg_root.mut) { unsafe = arg_root.mut; }
698+
ret {ex: arg_root.ex, mut: unsafe};
699699
}
700700
_ {}
701701
}
702702
}
703703
_ {}
704704
}
705705
}
706-
ret base_root;
706+
ret {ex: base_root.ex, mut: unsafe};
707707
}
708708

709-
fn inner_mut(ds: @[deref]) -> [ty::t] {
710-
for d: deref in *ds { if d.mut { ret [d.outer_t]; } }
711-
ret [];
709+
fn unsafe_set(from: option::t<unsafe_ty>) -> [unsafe_ty] {
710+
alt from { some(t) { [t] } _ { [] } }
712711
}
713712

714713
// Local Variables:

trunk/src/comp/middle/mut.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
105105
ret {ex: ex, ds: @ds};
106106
}
107107

108-
fn mut_field(ds: @[deref]) -> bool {
109-
for d: deref in *ds { if d.mut { ret true; } }
110-
ret false;
111-
}
112-
113108
// Actual mut-checking pass
114109

115110
type mut_map = std::map::hashmap<node_id, ()>;

0 commit comments

Comments
 (0)