Skip to content

Commit 5cd10d2

Browse files
committed
Error message, instead of segfault, when recursive types are used.
1 parent 1b67fbd commit 5cd10d2

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

src/comp/front/ast.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,14 @@ fn is_constraint_arg(@expr e) -> bool {
503503
}
504504
}
505505

506+
fn eq_ty(&@ty a, &@ty b) -> bool {
507+
ret a == b;
508+
}
509+
510+
fn hash_ty(&@ty t) -> uint {
511+
ret t.span.lo << 16u + t.span.hi;
512+
}
513+
506514
//
507515
// Local Variables:
508516
// mode: rust

src/comp/middle/ty.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ type item_table = hashmap[ast::def_id,any_item];
6161

6262
type mt = rec(t ty, ast::mutability mut);
6363

64+
tag cached_ty {
65+
in_progress;
66+
done(t);
67+
}
68+
6469
// Contains information needed to resolve types and (in the future) look up
6570
// the types of AST nodes.
6671
type creader_cache = hashmap[tup(int,uint,uint),ty::t];
@@ -71,7 +76,8 @@ type ctxt = rec(@type_store ts,
7176
item_table items,
7277
type_cache tcache,
7378
creader_cache rcache,
74-
hashmap[t,str] short_names_cache);
79+
hashmap[t,str] short_names_cache,
80+
hashmap[@ast::ty,cached_ty] ast_ty_to_ty_cache);
7581
type ty_ctxt = ctxt; // Needed for disambiguation from unify::ctxt.
7682

7783
// 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 {
245251
tcache = tcache,
246252
rcache = mk_rcache(),
247253
short_names_cache =
248-
map::mk_hashmap[ty::t,str](ty::hash_ty, ty::eq_ty));
254+
map::mk_hashmap[ty::t,str](ty::hash_ty, ty::eq_ty),
255+
ast_ty_to_ty_cache =
256+
map::mk_hashmap[@ast::ty,cached_ty](ast::hash_ty, ast::eq_ty));
249257

250258
populate_type_store(cx);
251259
ret cx;

src/comp/middle/typeck.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ fn ast_mode_to_mode(ast::mode mode) -> ty::mode {
227227
// notion of a type. `getter` is a function that returns the type
228228
// corresponding to a definition ID:
229229
fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
230+
alt (tcx.ast_ty_to_ty_cache.find(ast_ty)) {
231+
case (some[ty::cached_ty](ty::done(?ty))) { ret ty; }
232+
case (some[ty::cached_ty](ty::in_progress)) {
233+
tcx.sess.span_err(ast_ty.span, "illegal recursive type "
234+
+ "(insert a tag in the cycle, if this is desired)");
235+
}
236+
case (none[ty::cached_ty]) { } /* go on */
237+
}
238+
tcx.ast_ty_to_ty_cache.insert(ast_ty, ty::in_progress);
239+
230240
fn ast_arg_to_arg(&ty::ctxt tcx,
231241
&ty_getter getter,
232242
&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 {
329339
case (_) {
330340
tcx.sess.span_err(ast_ty.span,
331341
"found type name used as a variable");
332-
fail; }
342+
}
333343
}
334344

335345
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 {
360370
typ = ty::rename(tcx, typ, cname_str);
361371
}
362372
}
373+
374+
tcx.ast_ty_to_ty_cache.insert(ast_ty, ty::done(typ));
363375
ret typ;
364376
}
365377

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// error-pattern:illegal recursive type
2+
type t1 = rec(int foo, t1 foolish);
3+
4+
fn main() {}

0 commit comments

Comments
 (0)