about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2011-06-02 14:03:17 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2011-06-02 14:03:17 -0700
commit5cd10d2fef8ffa68903b18726f19ac52a04725cc (patch)
tree67a1fdbd048b6297a38ad645e37d61e00bb19eb0 /src/comp/middle
parent1b67fbdfd30ef55510ef57e68f106a72cd19b7be (diff)
downloadrust-5cd10d2fef8ffa68903b18726f19ac52a04725cc.tar.gz
rust-5cd10d2fef8ffa68903b18726f19ac52a04725cc.zip
Error message, instead of segfault, when recursive types are used.
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/ty.rs12
-rw-r--r--src/comp/middle/typeck.rs14
2 files changed, 23 insertions, 3 deletions
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index f936d7513e5..70557a97ed4 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -61,6 +61,11 @@ type item_table = hashmap[ast::def_id,any_item];
 
 type mt = rec(t ty, ast::mutability mut);
 
+tag cached_ty {
+    in_progress;
+    done(t);
+}
+
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
 type creader_cache = hashmap[tup(int,uint,uint),ty::t];
@@ -71,7 +76,8 @@ type ctxt = rec(@type_store ts,
                 item_table items,
                 type_cache tcache,
                 creader_cache rcache,
-                hashmap[t,str] short_names_cache);
+                hashmap[t,str] short_names_cache,
+                hashmap[@ast::ty,cached_ty] ast_ty_to_ty_cache);
 type ty_ctxt = ctxt;    // Needed for disambiguation from unify::ctxt.
 
 // Convert from method type to function type.  Pretty easy; we just drop
@@ -245,7 +251,9 @@ fn mk_ctxt(session::session s, resolve::def_map dm) -> ctxt {
             tcache = tcache,
             rcache = mk_rcache(),
             short_names_cache =
-            map::mk_hashmap[ty::t,str](ty::hash_ty, ty::eq_ty));
+            map::mk_hashmap[ty::t,str](ty::hash_ty, ty::eq_ty),
+            ast_ty_to_ty_cache = 
+            map::mk_hashmap[@ast::ty,cached_ty](ast::hash_ty, ast::eq_ty));
 
     populate_type_store(cx);
     ret cx;
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 6b69dba49ae..690ecd4aba8 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -227,6 +227,16 @@ fn ast_mode_to_mode(ast::mode mode) -> ty::mode {
 // notion of a type. `getter` is a function that returns the type
 // corresponding to a definition ID:
 fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
+    alt (tcx.ast_ty_to_ty_cache.find(ast_ty)) {
+        case (some[ty::cached_ty](ty::done(?ty))) { ret ty; } 
+        case (some[ty::cached_ty](ty::in_progress)) {
+            tcx.sess.span_err(ast_ty.span, "illegal recursive type "
+                + "(insert a tag in the cycle, if this is desired)");
+        }
+        case (none[ty::cached_ty]) { } /* go on */
+    }
+    tcx.ast_ty_to_ty_cache.insert(ast_ty, ty::in_progress);
+    
     fn ast_arg_to_arg(&ty::ctxt tcx,
                       &ty_getter getter,
                       &rec(ast::mode mode, @ast::ty ty) arg)
@@ -329,7 +339,7 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
                 case (_)                   {
                     tcx.sess.span_err(ast_ty.span,
                        "found type name used as a variable");
-                    fail; }
+                }
             }
 
             cname = some(path_to_str(path));
@@ -360,6 +370,8 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
             typ = ty::rename(tcx, typ, cname_str);
         }
     }
+
+    tcx.ast_ty_to_ty_cache.insert(ast_ty, ty::done(typ));
     ret typ;
 }