about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-09-13 12:31:16 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-09-13 13:05:59 +0200
commit2f402343c9327ba3f3f442b26ccb58cd0e3a09e4 (patch)
treeb193d017da9003948df562ed857df97c3b5b1e1c /src/comp
parent3e92f90952a2f9afc64079dc0f2dd02dd6484388 (diff)
downloadrust-2f402343c9327ba3f3f442b26ccb58cd0e3a09e4.tar.gz
rust-2f402343c9327ba3f3f442b26ccb58cd0e3a09e4.zip
Make for loop alias-safe
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/alias.rs66
-rw-r--r--src/comp/middle/trans.rs20
-rw-r--r--src/comp/middle/trans_alt.rs2
3 files changed, 36 insertions, 52 deletions
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs
index 23da42291aa..be996ae39ec 100644
--- a/src/comp/middle/alias.rs
+++ b/src/comp/middle/alias.rs
@@ -59,23 +59,12 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> copy_map {
 fn visit_fn(f: ast::_fn, _tp: [ast::ty_param], _sp: span, _name: fn_ident,
             _id: ast::node_id, sc: scope, v: vt<scope>) {
     visit::visit_fn_decl(f.decl, sc, v);
-    let scope =
-        alt f.proto {
-
-
-
-          // Blocks need to obey any restrictions from the enclosing scope.
-          ast::proto_block. | ast::proto_closure. {
-            sc
-          }
-
-
-
-          // Non capturing functions start out fresh.
-          _ {
-            @[]
-          }
-        };
+    let scope = alt f.proto {
+      // Blocks need to obey any restrictions from the enclosing scope.
+      ast::proto_block. | ast::proto_closure. { sc }
+      // Non capturing functions start out fresh.
+      _ { @[] }
+    };
     v.visit_block(f.body, scope, v);
 }
 
@@ -279,7 +268,7 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
         type info = {id: node_id, mutable unsafe: [ty::t], span: span};
         let binding_info: [info] = [];
         for pat in a.pats {
-            for proot in *pattern_roots(cx.tcx, root.ds, pat) {
+            for proot in *pattern_roots(cx.tcx, *root.ds, pat) {
                 let canon_id = pat_id_map.get(proot.name);
                 // FIXME I wanted to use a block, but that hit a
                 // typestate bug.
@@ -327,33 +316,34 @@ fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
              sc: scope, v: vt<scope>) {
     v.visit_expr(seq, sc, v);
     let root = expr_root(cx.tcx, seq, false);
-    let unsafe = inner_mut(root.ds);
 
     // If this is a mutable vector, don't allow it to be touched.
     let seq_t = ty::expr_ty(cx.tcx, seq);
-    let elt_t;
+    let ext_ds = *root.ds;
     alt ty::struct(cx.tcx, seq_t) {
       ty::ty_vec(mt) {
-        if mt.mut != ast::imm { unsafe = [seq_t]; }
-        elt_t = mt.ty;
+        if mt.mut != ast::imm {
+            ext_ds += [@{mut: true, kind: index, outer_t: seq_t}];
+        }
       }
-      ty::ty_str. { elt_t = ty::mk_mach(cx.tcx, ast::ty_u8); }
+      _ {}
     }
     let root_var = path_def_id(cx, root.ex);
-    let new_sc =
-        @{root_var: root_var,
-          // FIXME reenable when trans knows how to copy for vars
-          node_id: 0, // blk.node.id,
-          ty: elt_t,
-          span: local.node.pat.span,
-          local_id: cx.next_local,
-          bindings: ast_util::pat_binding_ids(local.node.pat),
-          unsafe_tys: unsafe,
-          depends_on: deps(sc, root_var),
-          mutable ok: valid,
-          mutable given_up: false};
+    let new_sc = *sc;
+    for proot in *pattern_roots(cx.tcx, ext_ds, local.node.pat) {
+        new_sc += [@{root_var: root_var,
+                     node_id: proot.id,
+                     ty: ty::node_id_to_type(cx.tcx, proot.id),
+                     span: proot.span,
+                     local_id: cx.next_local,
+                     bindings: [proot.id],
+                     unsafe_tys: inner_mut(proot.ds),
+                     depends_on: deps(sc, root_var),
+                     mutable ok: valid,
+                     mutable given_up: false}];
+    }
     register_locals(cx, local.node.pat);
-    visit::visit_block(blk, @(*sc + [new_sc]), v);
+    visit::visit_block(blk, @new_sc, v);
 }
 
 fn check_var(cx: ctx, ex: @ast::expr, p: ast::path, id: ast::node_id,
@@ -555,7 +545,7 @@ fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool {
 
 type pattern_root = {id: node_id, name: ident, ds: @[deref], span: span};
 
-fn pattern_roots(tcx: ty::ctxt, base: @[deref], pat: @ast::pat)
+fn pattern_roots(tcx: ty::ctxt, base: [deref], pat: @ast::pat)
     -> @[pattern_root] {
     fn walk(tcx: ty::ctxt, base: [deref], pat: @ast::pat,
             &set: [pattern_root]) {
@@ -587,7 +577,7 @@ fn pattern_roots(tcx: ty::ctxt, base: @[deref], pat: @ast::pat)
         }
     }
     let set = [];
-    walk(tcx, *base, pat, set);
+    walk(tcx, base, pat, set);
     ret @set;
 }
 
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 21fb132c7a8..419b8fb4ae4 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -2418,22 +2418,16 @@ fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
 
 fn trans_for(cx: @block_ctxt, local: @ast::local, seq: @ast::expr,
              body: ast::blk) -> result {
-    fn inner(cx: @block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t,
+    fn inner(bcx: @block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t,
              body: ast::blk, outer_next_cx: @block_ctxt) -> @block_ctxt {
-        let next_cx = new_sub_block_ctxt(cx, "next");
+        let next_cx = new_sub_block_ctxt(bcx, "next");
         let scope_cx =
-            new_loop_scope_block_ctxt(cx,
-                                      option::some::<@block_ctxt>(next_cx),
+            new_loop_scope_block_ctxt(bcx, option::some(next_cx),
                                       outer_next_cx, "for loop scope");
-        Br(cx, scope_cx.llbb);
-        let {bcx: bcx, val: dst} = alloc_local(scope_cx, local);
-        let val =
-            load_if_immediate(bcx, PointerCast(bcx, curr, val_ty(dst)), t);
-        let bcx = copy_val(bcx, INIT, dst, val, t);
-        add_clean(scope_cx, dst, t);
-        let bcx =
-            trans_alt::bind_irrefutable_pat(bcx, local.node.pat, dst,
-                                            cx.fcx.lllocals, false);
+        Br(bcx, scope_cx.llbb);
+        curr = PointerCast(bcx, curr, T_ptr(type_of_or_i8(bcx, t)));
+        bcx = trans_alt::bind_irrefutable_pat(scope_cx, local.node.pat, curr,
+                                              bcx.fcx.lllocals, false);
         bcx = trans_block(bcx, body, return).bcx;
         if !is_terminated(bcx) {
             Br(bcx, next_cx.llbb);
diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs
index 0b84f85054a..2410cd2ea47 100644
--- a/src/comp/middle/trans_alt.rs
+++ b/src/comp/middle/trans_alt.rs
@@ -571,7 +571,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
     let ccx = bcx.fcx.lcx.ccx;
     alt pat.node {
       ast::pat_bind(_) {
-        if make_copy {
+        if make_copy || ccx.copy_map.contains_key(pat.id) {
             let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
             // FIXME: Could constrain pat_bind to make this
             // check unnecessary.