about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-03-15 16:36:58 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-03-15 16:38:08 -0700
commitbc21a5ddbe70b2a0c68db9e632ee7e78de9fa59e (patch)
tree6d76e90fd9280b448fe5a7a6771661e9c6d852ea /src/rustc
parent041c9a0863e01f2cfa92816eaaf8ea295f851157 (diff)
downloadrust-bc21a5ddbe70b2a0c68db9e632ee7e78de9fa59e.tar.gz
rust-bc21a5ddbe70b2a0c68db9e632ee7e78de9fa59e.zip
rustc: Create self region bindings, and forbid the self region from being used in places it shouldn't be
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/tyencode.rs3
-rw-r--r--src/rustc/middle/region.rs46
-rw-r--r--src/rustc/middle/regionck.rs4
-rw-r--r--src/rustc/middle/ty.rs6
-rw-r--r--src/rustc/middle/typeck.rs13
-rw-r--r--src/rustc/util/ppaux.rs1
6 files changed, 57 insertions, 16 deletions
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index 4dd229c7dd2..31270053078 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -103,6 +103,9 @@ fn enc_region(w: io::writer, cx: @ctxt, r: ty::region) {
         ty::re_block(nid) {
             w.write_char('b'); w.write_int(nid); w.write_char('|');
         }
+        ty::re_self(did) {
+            w.write_char('s'); w.write_str(cx.ds(did)); w.write_char('|');
+        }
         ty::re_inferred { w.write_char('?'); }
     }
 }
diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs
index 0b33b6e2631..e1b467ece01 100644
--- a/src/rustc/middle/region.rs
+++ b/src/rustc/middle/region.rs
@@ -65,13 +65,19 @@ type ctxt = {
     parent: parent,
 
     /* True if we're within the pattern part of an alt, false otherwise. */
-    in_alt: bool
+    in_alt: bool,
+
+    /*
+     * Points to the site of the current typeclass implementation, or none if
+     * we're outside one.
+     */
+    self_binding: option<ast::def_id>
 };
 
 fn region_to_scope(region_map: @region_map, region: ty::region)
         -> ast::node_id {
     ret alt region {
-        ty::re_caller(def_id) { def_id.node }
+        ty::re_caller(def_id) | ty::re_self(def_id) { def_id.node }
         ty::re_named(def_id) { region_map.region_name_to_fn.get(def_id) }
         ty::re_block(node_id) { node_id }
         ty::re_inferred { fail "unresolved region in region_to_scope" }
@@ -115,7 +121,21 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
     alt ty.node {
         ast::ty_rptr({id: region_id, node: node}, _) {
             alt node {
-                ast::re_inferred | ast::re_self { /* no-op */ }
+                ast::re_inferred { /* no-op */ }
+                ast::re_self {
+                    alt cx.self_binding {
+                        some(def_id) {
+                            let region = ty::re_self(def_id);
+                            let rm = cx.region_map;
+                            rm.ast_type_to_region.insert(region_id, region);
+                        }
+                        none {
+                            cx.sess.span_err(ty.span,
+                                             "the `self` region is not \
+                                              allowed here");
+                        }
+                    }
+                }
                 ast::re_named(ident) {
                     // If at item scope, introduce or reuse a binding. If at
                     // block scope, require that the binding be introduced.
@@ -281,13 +301,22 @@ fn resolve_local(local: @ast::local, cx: ctxt, visitor: visit::vt<ctxt>) {
 
 fn resolve_item(item: @ast::item, cx: ctxt, visitor: visit::vt<ctxt>) {
     // Items create a new outer block scope as far as we're concerned.
-    let parent = alt item.node {
-        ast::item_fn(_, _, _) | ast::item_enum(_, _) { pa_fn_item(item.id) }
-        _ { pa_item(item.id) }
+    let parent;
+    let mut self_binding = cx.self_binding;
+    alt item.node {
+        ast::item_fn(_, _, _) | ast::item_enum(_, _) {
+            parent = pa_fn_item(item.id);
+        }
+        ast::item_impl(_, _, _, _) {
+            self_binding = some({crate: ast::local_crate, node: item.id});
+            parent = pa_item(item.id);
+        }
+        _ { parent = pa_item(item.id); }
     };
     let new_cx: ctxt = {bindings: @list::nil,
                         parent: parent,
-                        in_alt: false
+                        in_alt: false,
+                        self_binding: self_binding
                         with cx};
     visit::visit_item(item, new_cx, visitor);
 }
@@ -307,7 +336,8 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
                     mut bindings: @list::nil,
                     mut queued_locals: [],
                     parent: pa_crate,
-                    in_alt: false};
+                    in_alt: false,
+                    self_binding: none};
     let visitor = visit::mk_vt(@{
         visit_block: resolve_block,
         visit_item: resolve_item,
diff --git a/src/rustc/middle/regionck.rs b/src/rustc/middle/regionck.rs
index 1b73704c301..42d9a51dd47 100644
--- a/src/rustc/middle/regionck.rs
+++ b/src/rustc/middle/regionck.rs
@@ -28,7 +28,9 @@ fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
             alt ty::get(t).struct {
                 ty::ty_rptr(region, _) {
                     alt region {
-                        ty::re_named(_) | ty::re_caller(_) { /* ok */ }
+                        ty::re_named(_) | ty::re_caller(_) | ty::re_self(_) {
+                            /* ok */
+                        }
                         ty::re_block(rbi) {
                             let referent_block_id = rbi;
                             let enclosing_block_id = alt cx.enclosing_block {
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 74dc8dde5fc..9d581287470 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -233,6 +233,7 @@ type fn_ty = {proto: ast::proto,
 enum region {
     re_named(def_id),
     re_caller(def_id),
+    re_self(def_id),
     re_block(node_id),
     re_inferred         /* currently unresolved (for typedefs) */
 }
@@ -1152,8 +1153,9 @@ fn hash_type_structure(st: sty) -> uint {
         alt r {
           re_named(_)   { 1u }
           re_caller(_)  { 2u }
-          re_block(_)   { 3u }
-          re_inferred   { 4u }
+          re_self(_)    { 3u }
+          re_block(_)   { 4u }
+          re_inferred   { 5u }
         }
     }
     alt st {
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 1e092a6eb78..5bfca5805ce 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -254,10 +254,11 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
     fn subst_inferred_regions(tcx: ty::ctxt, use_site: ast::node_id,
                               ty: ty::t) -> ty::t {
         ret ty::fold_ty(tcx, ty::fm_rptr({|r|
-            if r == ty::re_inferred {
-                tcx.region_map.ast_type_to_inferred_region.get(use_site)
-            } else {
-                r
+            alt r {
+                ty::re_inferred | ty::re_self(_) {
+                    tcx.region_map.ast_type_to_inferred_region.get(use_site)
+                }
+                _ { r }
             }
         }), ty);
     }
@@ -1462,7 +1463,9 @@ fn instantiate_self_regions(pcx: pat_ctxt, args: [ty::t]) -> [ty::t] {
         if ty::type_has_rptrs(arg_ty) {
             ty::fold_ty(pcx.fcx.ccx.tcx, ty::fm_rptr({|r|
                 alt r {
-                    ty::re_inferred | ty::re_caller(_) { pcx.pat_region }
+                    ty::re_inferred | ty::re_caller(_) | ty::re_self(_) {
+                        pcx.pat_region
+                    }
                     _ { r }
                 }
             }), arg_ty)
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index 0541c0d9d15..a08796d7f36 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -73,6 +73,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
           re_named(_)   { "<name>."   }     // TODO: include name
           re_caller(_)  { "<caller>." }
           re_block(_)   { "<block>."  }     // TODO: include line number
+          re_self(_)    { "self."     }
           re_inferred   { ""          }
         }
     }