about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-04-10 18:33:20 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-04-11 12:07:19 -0700
commitc720ffdbc428336546448daf2f806428cc22db06 (patch)
tree77581b33368c5986398575e53593c0ef7ce1ac87 /src
parent9d7e4aefee194e3d6f0cf15d6adf1f41c7cb3935 (diff)
downloadrust-c720ffdbc428336546448daf2f806428cc22db06.tar.gz
rust-c720ffdbc428336546448daf2f806428cc22db06.zip
Improve region code surrounding slice types.
Diffstat (limited to 'src')
-rw-r--r--src/rustc/middle/infer.rs9
-rw-r--r--src/rustc/middle/region.rs51
-rw-r--r--src/rustc/middle/typeck.rs100
3 files changed, 78 insertions, 82 deletions
diff --git a/src/rustc/middle/infer.rs b/src/rustc/middle/infer.rs
index aac422dbca7..ce836221d7c 100644
--- a/src/rustc/middle/infer.rs
+++ b/src/rustc/middle/infer.rs
@@ -908,6 +908,15 @@ fn super_tys<C:combine>(
         }
       }
 
+      (ty::ty_evec(a_mt, ty::vstore_slice(a_r)),
+       ty::ty_evec(b_mt, ty::vstore_slice(b_r))) {
+        self.contraregions(a_r, b_r).chain {|r|
+            self.mts(a_mt, b_mt).chain {|mt|
+                ok(ty::mk_evec(tcx, mt, ty::vstore_slice(r)))
+            }
+        }
+      }
+
       (ty::ty_res(a_id, a_t, a_tps), ty::ty_res(b_id, b_t, b_tps))
       if a_id == b_id {
         self.tys(a_t, b_t).chain {|t|
diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs
index 39f08983b4b..bc662738ba4 100644
--- a/src/rustc/middle/region.rs
+++ b/src/rustc/middle/region.rs
@@ -168,9 +168,10 @@ type region_map = {
     ast_type_to_inferred_region: hashmap<ast::node_id,ty::region>,
     /*
      * Mapping from an address-of operator or alt expression to its containing
-     * block. This is used as the region if the operand is an rvalue.
+     * region (usually ty::region_scope(block). This is used as the region if
+     * the operand is an rvalue.
      */
-    rvalue_to_block: hashmap<ast::node_id,ast::node_id>
+    rvalue_to_region: hashmap<ast::node_id,ty::region>
 };
 
 type region_scope = @{
@@ -366,41 +367,26 @@ fn get_inferred_region(cx: ctxt, sp: syntax::codemap::span) -> ty::region {
     }
 }
 
-fn resolve_region_binding(cx: ctxt, span: span, region: ast::region) {
-
-    let id = region.id;
-    let rm = cx.region_map;
+fn resolve_region_binding(cx: ctxt, span: span,
+                          region: ast::region) -> ty::region {
     alt region.node {
-      ast::re_inferred {
-        // option::may(cx.scope.resolve_anon()) {|r|
-        //     rm.ast_type_to_region.insert(id, r);
-        // }
-      }
-
-      ast::re_static { /* fallthrough */ }
-
+      ast::re_inferred { ty::re_default }
+      ast::re_static { ty::re_static }
       ast::re_named(ident) {
         alt cx.scope.resolve_ident(ident) {
-          some(r) {
-            rm.ast_type_to_region.insert(id, r);
-          }
-
+          some(r) { r }
           none {
-            cx.sess.span_err(
+            cx.sess.span_fatal(
                 span,
                 #fmt["the region `%s` is not declared", ident]);
           }
         }
       }
-
       ast::re_self {
         alt cx.scope.resolve_self() {
-          some(r) {
-            rm.ast_type_to_region.insert(id, r);
-          }
-
+          some(r) { r }
           none {
-            cx.sess.span_err(
+            cx.sess.span_fatal(
                 span,
                 "the `self` region is not allowed here");
           }
@@ -416,7 +402,8 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
     alt ty.node {
       ast::ty_vstore(_, ast::vstore_slice(r)) |
       ast::ty_rptr(r, _) {
-        resolve_region_binding(cx, ty.span, r);
+        let region = resolve_region_binding(cx, ty.span, r);
+        cx.region_map.ast_type_to_region.insert(ty.id, region);
       }
       _ { /* nothing to do */ }
     }
@@ -504,12 +491,17 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
                           in_alt: false with cx};
             visit::visit_expr(expr, new_cx, visitor);
         }
+        ast::expr_vstore(e, ast::vstore_slice(r)) {
+          let region = resolve_region_binding(cx, e.span, r);
+          cx.region_map.rvalue_to_region.insert(e.id, region);
+        }
         ast::expr_addr_of(_, subexpr) | ast::expr_alt(subexpr, _, _) {
             // Record the block that this expression appears in, in case the
             // operand is an rvalue.
             alt cx.parent {
                 pa_block(blk_id) {
-                    cx.region_map.rvalue_to_block.insert(subexpr.id, blk_id);
+                  let region = ty::re_scope(blk_id);
+                  cx.region_map.rvalue_to_region.insert(subexpr.id, region);
                 }
                 _ { cx.sess.span_bug(expr.span, "expr outside of block?!"); }
             }
@@ -522,7 +514,8 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
 fn resolve_local(local: @ast::local, cx: ctxt, visitor: visit::vt<ctxt>) {
     alt cx.parent {
         pa_block(blk_id) {
-            cx.region_map.rvalue_to_block.insert(local.node.id, blk_id);
+          let region = ty::re_scope(blk_id);
+          cx.region_map.rvalue_to_region.insert(local.node.id, region);
         }
         _ { cx.sess.span_bug(local.span, "local outside of block?!"); }
     }
@@ -566,7 +559,7 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
                                   local_blocks: map::int_hash(),
                                   ast_type_to_inferred_region:
                                     map::int_hash(),
-                                  rvalue_to_block: map::int_hash()},
+                                  rvalue_to_region: map::int_hash()},
                     scope: root_scope(0),
                     mut queued_locals: [],
                     parent: pa_crate,
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 46e8a2ad096..a5affba6bec 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -276,49 +276,39 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
 
 enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), }
 
-fn ast_region_to_region(tcx: ty::ctxt,
-                        region: ast::region) -> ty::region {
-    alt region.node {
-      ast::re_inferred {
-        // this must be replaced later by a fixup_regions() pass
-        ty::re_default
+fn ast_ty_vstore_to_vstore(tcx: ty::ctxt, ty: @ast::ty,
+                           v: ast::vstore) -> ty::vstore {
+    alt v {
+      ast::vstore_fixed(none) {
+        tcx.sess.span_bug(ty.span,
+                          "implied fixed length in ast_ty_vstore_to_vstore");
       }
-      ast::re_self | ast::re_named(_) {
-        tcx.region_map.ast_type_to_region.get(region.id)
+      ast::vstore_fixed(some(u)) {
+        ty::vstore_fixed(u)
       }
-      ast::re_static {
-        ty::re_static
+      ast::vstore_uniq { ty::vstore_uniq }
+      ast::vstore_box { ty::vstore_box }
+      ast::vstore_slice(r) {
+        ty::vstore_slice(tcx.region_map.ast_type_to_region.get(ty.id))
       }
     }
 }
 
-fn ast_vstore_to_vstore(tcx: ty::ctxt, span: span, n: option<uint>,
-                        v: ast::vstore) -> ty::vstore {
+fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint,
+                             v: ast::vstore) -> ty::vstore {
     alt v {
-      ast::vstore_fixed(none) {
-        alt n {
-          some(n) { ty::vstore_fixed(n) }
-          none {
-            tcx.sess.bug("implied fixed length in ast_vstore_to_vstore with \
-                          no default length")
-          }
-        }
-      }
+      ast::vstore_fixed(none) { ty::vstore_fixed(n) }
       ast::vstore_fixed(some(u)) {
-        alt n {
-          some(n) if n != u {
-            tcx.sess.span_err(span,
-                              #fmt("fixed-size sequence mismatch: %u vs. %u",
-                                   u, n));
-          }
-          _ { }
+        if n != u {
+            let s = #fmt("fixed-size sequence mismatch: %u vs. %u",u, n);
+            fcx.ccx.tcx.sess.span_err(e.span,s);
         }
         ty::vstore_fixed(u)
       }
       ast::vstore_uniq { ty::vstore_uniq }
       ast::vstore_box { ty::vstore_box }
-      ast::vstore_slice(region) {
-        ty::vstore_slice(ast_region_to_region(tcx, region))
+      ast::vstore_slice(r) {
+        ty::vstore_slice(region_of(fcx, e))
       }
     }
 }
@@ -408,7 +398,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
             ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt))
           }
           ast::ty_rptr(region, mt) {
-            let region = ast_region_to_region(tcx, region);
+            let region = tcx.region_map.ast_type_to_region.get(ast_ty.id);
             ty::mk_rptr(tcx, region, ast_mt_to_mt(tcx, mode, mt))
           }
           ast::ty_tup(fields) {
@@ -473,8 +463,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
             }
           }
           ast::ty_vstore(t, vst) {
-            let vst = ast_vstore_to_vstore(tcx, ast_ty.span, none, vst);
-            alt ty::get(do_ast_ty_to_ty(tcx, mode, t)).struct {
+            let vst = ast_ty_vstore_to_vstore(tcx, ast_ty, vst);
+            let ty = alt ty::get(do_ast_ty_to_ty(tcx, mode, t)).struct {
               ty::ty_vec(mt) { ty::mk_evec(tcx, mt, vst) }
               ty::ty_str { ty::mk_estr(tcx, vst) }
               _ {
@@ -482,7 +472,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
                                     "found sequence storage modifier \
                                      on non-sequence type");
               }
-            }
+            };
+            fixup_regions_to_block(tcx, ty, ast_ty)
           }
           ast::ty_constr(t, cs) {
             let mut out_cs = [];
@@ -2512,8 +2503,7 @@ fn region_of(fcx: @fn_ctxt, expr: @ast::expr) -> ty::region {
             }
         }
         _ {
-            let blk_id = fcx.ccx.tcx.region_map.rvalue_to_block.get(expr.id);
-            ret ty::re_scope(blk_id);
+            ret fcx.ccx.tcx.region_map.rvalue_to_region.get(expr.id);
         }
     }
 }
@@ -2849,27 +2839,32 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
     alt expr.node {
 
       ast::expr_vstore(ev, vst) {
-        alt ev.node {
+        let mut typ = alt ev.node {
           ast::expr_lit(@{node: ast::lit_str(s), span:_}) {
-            let tt = ast_vstore_to_vstore(tcx, expr.span,
-                                          some(str::len(s)), vst);
-            let typ = ty::mk_estr(tcx, tt);
-            fcx.write_ty(ev.id, typ);
-            fcx.write_ty(id, typ);
+            let tt = ast_expr_vstore_to_vstore(fcx, ev,
+                                               str::len(s), vst);
+            ty::mk_estr(tcx, tt)
           }
           ast::expr_vec(args, mutbl) {
-            let tt = ast_vstore_to_vstore(tcx, expr.span,
-                                          some(vec::len(args)), vst);
+            let tt = ast_expr_vstore_to_vstore(fcx, ev,
+                                               vec::len(args), vst);
             let t: ty::t = next_ty_var(fcx);
             for args.each {|e| bot |= check_expr_with(fcx, e, t); }
-            let typ = ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt);
-            fcx.write_ty(ev.id, typ);
-            fcx.write_ty(id, typ);
+            ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt)
           }
           _ {
-            tcx.sess.span_err(expr.span, "vstore modifier on non-sequence");
+            tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence")
+          }
+        };
+        alt vst {
+          ast::vstore_slice(_) {
+            let region = fcx.ccx.tcx.region_map.rvalue_to_region.get(ev.id);
+            typ = replace_default_region(tcx, region, typ);
           }
+          _ { }
         }
+        fcx.write_ty(ev.id, typ);
+        fcx.write_ty(id, typ);
       }
 
       ast::expr_lit(lit) {
@@ -3075,7 +3070,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
         let pattern_ty = next_ty_var(fcx);
         bot = check_expr_with(fcx, discrim, pattern_ty);
 
-        let parent_block = tcx.region_map.rvalue_to_block.get(discrim.id);
+        let parent_region = tcx.region_map.rvalue_to_region.get(discrim.id);
 
         // Typecheck the patterns first, so that we get types for all the
         // bindings.
@@ -3084,9 +3079,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
             let pcx = {
                 fcx: fcx,
                 map: pat_util::pat_id_map(tcx.def_map, arm.pats[0]),
-                alt_region: ty::re_scope(parent_block),
+                alt_region: parent_region,
                 block_region: ty::re_scope(arm.body.node.id),
-                pat_region: ty::re_scope(parent_block)
+                pat_region: parent_region
             };
 
             for arm.pats.each {|p| check_pat(pcx, p, pattern_ty);}
@@ -3529,8 +3524,7 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
       _ {/* fall through */ }
     }
 
-    let block_id = fcx.ccx.tcx.region_map.rvalue_to_block.get(local.node.id);
-    let region = ty::re_scope(block_id);
+    let region = fcx.ccx.tcx.region_map.rvalue_to_region.get(local.node.id);
     let pcx = {
         fcx: fcx,
         map: pat_util::pat_id_map(fcx.ccx.tcx.def_map, local.node.pat),