about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-01-26 11:35:30 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-01-26 11:35:30 -0800
commit596a97cf70b5329fb6bfe779ab1425a0e37a61d2 (patch)
tree00bbb948db05f0246ac06627cbea8d4e10644f56 /src
parent70c129f79b42f6020b2342e81bf96a0c701ee9e2 (diff)
downloadrust-596a97cf70b5329fb6bfe779ab1425a0e37a61d2.tar.gz
rust-596a97cf70b5329fb6bfe779ab1425a0e37a61d2.zip
Teach typeck to handle obj item names when used as type names, not just constructor calls.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/typeck.rs65
1 files changed, 47 insertions, 18 deletions
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 98fcc0d423c..e21e72a9e63 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -98,6 +98,24 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
         ret ty.fold_ty(replacer, t);
     }
 
+    fn instantiate(ty_getter getter, ast.def_id id,
+                   vec[@ast.ty] args) -> @ty.t {
+        // TODO: maybe record cname chains so we can do
+        // "foo = int" like OCaml?
+        auto ty_and_params = getter(id);
+        auto params = ty_and_params.params;
+        auto num_type_args = _vec.len[@ast.ty](args);
+        check(num_type_args == _vec.len[ast.ty_param](params));
+
+        auto param_map = common.new_def_hash[@ty.t]();
+        for each (uint i in _uint.range(0u, num_type_args)) {
+            auto arg = args.(i);
+            auto param = params.(i);
+            param_map.insert(param.id, ast_ty_to_ty(getter, arg));
+        }
+        ret replace_type_params(ty_and_params.ty, param_map);
+    }
+
     auto mut = ast.imm;
     auto sty;
     auto cname = none[str];
@@ -137,22 +155,10 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
             check (def != none[ast.def]);
             alt (option.get[ast.def](def)) {
                 case (ast.def_ty(?id)) {
-                    // TODO: maybe record cname chains so we can do
-                    // "foo = int" like OCaml?
-                    auto ty_and_params = getter(id);
-                    auto params = ty_and_params.params;
-                    auto num_type_params = _vec.len[@ast.ty](path.node.types);
-                    check(num_type_params == _vec.len[ast.ty_param](params));
-
-                    auto param_map = common.new_def_hash[@ty.t]();
-                    for each (uint i in _uint.range(0u, num_type_params)) {
-                        auto x = path.node.types.(i);
-                        auto y = params.(i);
-                        param_map.insert(y.id, ast_ty_to_ty(getter, x));
-                    }
-
-                    sty = replace_type_params(ty_and_params.ty,
-                                              param_map).struct;
+                    sty = instantiate(getter, id, path.node.types).struct;
+                }
+                case (ast.def_obj(?id))     {
+                    sty = instantiate(getter, id, path.node.types).struct;
                 }
                 case (ast.def_ty_arg(?id))  { sty = ty.ty_param(id); }
                 case (_)                    { fail; }
@@ -190,11 +196,21 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
 // ast_ty_to_ty.
 fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty.t {
     fn getter(@crate_ctxt ccx, ast.def_id id) -> ty_and_params {
-        check (ccx.item_types.contains_key(id));
         check (ccx.item_items.contains_key(id));
-        auto ty = ccx.item_types.get(id);
+        check (ccx.item_types.contains_key(id));
         auto item = ccx.item_items.get(id);
+        auto ty = ccx.item_types.get(id);
         auto params = ty_params_of_item(item);
+
+        alt (item.node) {
+            case (ast.item_obj(_,_,_,_,_)) {
+                // An obj used as a type name refers to the output type of the
+                // item (constructor).
+                ty = middle.ty.ty_fn_ret(ty);
+            }
+            case (_) { }
+        }
+
         ret rec(params = params, ty = ty);
     }
     auto f = bind getter(ccx, _);
@@ -243,6 +259,16 @@ fn collect_item_types(session.session sess, @ast.crate crate)
         auto item = id_to_ty_item.get(id);
         auto ty = ty_of_item(id_to_ty_item, item_to_ty, item);
         auto params = ty_params_of_item(item);
+
+        alt (item.node) {
+            case (ast.item_obj(_,_,_,_,_)) {
+                // An obj used as a type name refers to the output type of the
+                // item (constructor).
+                ty = middle.ty.ty_fn_ret(ty);
+            }
+            case (_) { }
+        }
+
         ret rec(params = params, ty = ty);
     }
 
@@ -400,6 +426,9 @@ fn collect_item_types(session.session sess, @ast.crate crate)
             case (ast.item_tag(_, _, _, ?def_id)) {
                 id_to_ty_item.insert(def_id, i);
             }
+            case (ast.item_obj(_, _, _, ?def_id, _)) {
+                id_to_ty_item.insert(def_id, i);
+            }
             case (_) { /* empty */ }
         }
         ret id_to_ty_item;