about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-03-13 15:52:45 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-03-13 15:53:16 -0700
commit8cbaebbb49a875728f95d413d7352f77cc97d04c (patch)
treecc4edc7021f3f8697d1e466156446f7252dbae03
parentb968c8e6cd362567bf0047a96d261691dfca43e8 (diff)
downloadrust-8cbaebbb49a875728f95d413d7352f77cc97d04c.tar.gz
rust-8cbaebbb49a875728f95d413d7352f77cc97d04c.zip
rustc: Get reference typedefs working
-rw-r--r--src/rustc/metadata/tyencode.rs1
-rw-r--r--src/rustc/middle/region.rs26
-rw-r--r--src/rustc/middle/regionck.rs4
-rw-r--r--src/rustc/middle/ty.rs18
-rw-r--r--src/rustc/middle/typeck.rs27
-rw-r--r--src/rustc/util/ppaux.rs1
6 files changed, 62 insertions, 15 deletions
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index 92ede889016..81e9eff4a9d 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -103,6 +103,7 @@ 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_inferred { w.write_char('?'); }
     }
 }
 fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs
index 73409893e5c..bacde1d0293 100644
--- a/src/rustc/middle/region.rs
+++ b/src/rustc/middle/region.rs
@@ -15,9 +15,10 @@ import std::map::hashmap;
 
 /* Represents the type of the most immediate parent node. */
 enum parent {
-    pa_item(ast::node_id),
+    pa_fn_item(ast::node_id),
     pa_block(ast::node_id),
     pa_nested_fn(ast::node_id),
+    pa_item(ast::node_id),
     pa_crate
 }
 
@@ -66,6 +67,7 @@ fn region_to_scope(region_map: @region_map, region: ty::region)
         ty::re_caller(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" }
     };
 }
 
@@ -90,10 +92,11 @@ fn get_inferred_region(cx: ctxt, sp: syntax::codemap::span) -> ty::region {
     // TODO: What do we do if we're in an alt?
 
     ret alt cx.parent {
-        pa_item(item_id) | pa_nested_fn(item_id) {
+        pa_fn_item(item_id) | pa_nested_fn(item_id) {
             ty::re_caller({crate: ast::local_crate, node: item_id})
         }
         pa_block(block_id) { ty::re_block(block_id) }
+        pa_item(_) { ty::re_inferred }
         pa_crate { cx.sess.span_bug(sp, "inferred region at crate level?!"); }
     }
 }
@@ -121,10 +124,16 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
                             region = ty::re_named(def_id);
 
                             alt cx.parent {
-                                pa_item(fn_id) | pa_nested_fn(fn_id) {
+                                pa_fn_item(fn_id) | pa_nested_fn(fn_id) {
                                     let rf = cx.region_map.region_name_to_fn;
                                     rf.insert(def_id, fn_id);
                                 }
+                                pa_item(_) {
+                                    cx.sess.span_err(ty.span,
+                                                     "named region not " +
+                                                     "allowed in this " +
+                                                     "context");
+                                }
                                 pa_block(_) {
                                     cx.sess.span_err(ty.span,
                                                      "unknown region `" +
@@ -152,7 +161,10 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
 
 fn record_parent(cx: ctxt, child_id: ast::node_id) {
     alt cx.parent {
-        pa_item(parent_id) | pa_block(parent_id) | pa_nested_fn(parent_id) {
+        pa_fn_item(parent_id) |
+        pa_item(parent_id) |
+        pa_block(parent_id) |
+        pa_nested_fn(parent_id) {
             cx.region_map.parents.insert(child_id, parent_id);
         }
         pa_crate { /* no-op */ }
@@ -231,8 +243,12 @@ fn resolve_expr(expr: @ast::expr, 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(_, _, _)   { pa_fn_item(item.id) }
+        _                       { pa_item(item.id)    }
+    };
     let new_cx: ctxt = {bindings: @list::nil,
-                        parent: pa_item(item.id),
+                        parent: parent,
                         in_alt: false
                         with cx};
     visit::visit_item(item, new_cx, visitor);
diff --git a/src/rustc/middle/regionck.rs b/src/rustc/middle/regionck.rs
index 65b1d0673a6..702c844c0f2 100644
--- a/src/rustc/middle/regionck.rs
+++ b/src/rustc/middle/regionck.rs
@@ -49,6 +49,10 @@ fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
                                                      "escapes its block");
                             }
                         }
+                        ty::re_inferred {
+                            cx.tcx.sess.span_bug(expr.span,
+                                                 "unresolved region");
+                        }
                     }
                 }
                 _ { /* no-op */ }
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 5f5ac939a22..06764a472ce 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -35,7 +35,7 @@ export field;
 export field_idx;
 export get_field;
 export get_fields;
-export fm_general;
+export fm_general, fm_rptr;
 export get_element_type;
 export is_binopable;
 export is_pred_ty;
@@ -88,7 +88,7 @@ export ty_uint, mk_uint, mk_mach_uint;
 export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
 export ty_var, mk_var;
 export ty_self, mk_self;
-export region, re_named, re_caller, re_block;
+export region, re_named, re_caller, re_block, re_inferred;
 export get, type_has_params, type_has_vars, type_has_rptrs, type_id;
 export same_type;
 export ty_var_id;
@@ -234,7 +234,8 @@ type fn_ty = {proto: ast::proto,
 enum region {
     re_named(def_id),
     re_caller(def_id),
-    re_block(node_id)
+    re_block(node_id),
+    re_inferred         /* currently unresolved (for typedefs) */
 }
 
 // NB: If you change this, you'll probably want to change the corresponding
@@ -571,6 +572,7 @@ fn walk_ty(cx: ctxt, ty: t, f: fn(t)) {
 enum fold_mode {
     fm_var(fn@(int) -> t),
     fm_param(fn@(uint, def_id) -> t),
+    fm_rptr(fn@(region) -> region),
     fm_general(fn@(t) -> t),
 }
 
@@ -581,6 +583,7 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
     alt fld {
       fm_var(_) { if !tb.has_vars { ret ty; } }
       fm_param(_) { if !tb.has_params { ret ty; } }
+      fm_rptr(_) { if !tb.has_rptrs { ret ty; } }
       fm_general(_) {/* no fast path */ }
     }
 
@@ -597,9 +600,6 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
       ty_ptr(tm) {
         ty = mk_ptr(cx, {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl});
       }
-      ty_rptr(r, tm) {
-        ty = mk_rptr(cx, r, {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl});
-      }
       ty_vec(tm) {
         ty = mk_vec(cx, {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl});
       }
@@ -647,6 +647,11 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
       ty_param(id, did) {
         alt fld { fm_param(folder) { ty = folder(id, did); } _ {} }
       }
+      ty_rptr(r, tm) {
+        let region = alt fld { fm_rptr(folder) { folder(r) } _ { r } };
+        ty = mk_rptr(cx, region,
+                     {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl});
+      }
       ty_constr(subty, cs) {
           ty = mk_constr(cx, fold_ty(cx, fld, subty), cs);
       }
@@ -1161,6 +1166,7 @@ fn hash_type_structure(st: sty) -> uint {
           re_named(_)   { 1u }
           re_caller(_)  { 2u }
           re_block(_)   { 3u }
+          re_inferred   { 4u }
         }
     }
     alt st {
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index e8d47886665..dbd0baf5dfa 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -247,10 +247,19 @@ enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), }
 // internal notion of a type. `getter` is a function that returns the type
 // corresponding to a definition ID:
 fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
-    fn getter(tcx: ty::ctxt, _use_site: ast::node_id, mode: mode,
+    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
+            }
+        }), ty);
+    }
+    fn getter(tcx: ty::ctxt, use_site: ast::node_id, mode: mode,
               id: ast::def_id) -> ty::ty_param_bounds_and_ty {
-        // FIXME (pcwalton): Doesn't work with region inference.
-        alt mode {
+        let tpt = alt mode {
           m_check | m_check_tyvar(_) { ty::lookup_item_type(tcx, id) }
           m_collect {
             if id.crate != ast::local_crate { csearch::get_type(tcx, id) }
@@ -268,7 +277,13 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
                 }
             }
           }
+        };
+
+        if ty::type_has_rptrs(tpt.ty) {
+            ret {bounds: tpt.bounds,
+                 ty: subst_inferred_regions(tcx, use_site, tpt.ty)};
         }
+        ret tpt;
     }
     fn ast_mt_to_mt(tcx: ty::ctxt, use_site: ast::node_id, mode: mode,
                     mt: ast::mt) -> ty::mt {
@@ -327,7 +342,11 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
           ast::ty_rptr(region, mt) {
             let region = alt region.node {
                 ast::re_inferred | ast::re_self {
-                    tcx.region_map.ast_type_to_inferred_region.get(ast_ty.id)
+                    let attir = tcx.region_map.ast_type_to_inferred_region;
+                    alt attir.find(ast_ty.id) {
+                        some(resolved_region) { resolved_region }
+                        none { ty::re_inferred }
+                    }
                 }
                 ast::re_named(_) {
                     tcx.region_map.ast_type_to_region.get(region.id)
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index 711b27327c2..0541c0d9d15 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_inferred   { ""          }
         }
     }