Properly check enum types for recursion

Closes #742
This commit is contained in:
Marijn Haverbeke 2012-01-27 16:01:04 +01:00
parent 03e9dac09a
commit dc55c06aa3
3 changed files with 25 additions and 6 deletions

View file

@ -172,6 +172,7 @@ export type_is_str;
export type_is_unique;
export type_is_enum;
export type_is_c_like_enum;
export type_structurally_contains;
export type_structurally_contains_uniques;
export type_autoderef;
export type_param;

View file

@ -259,8 +259,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
some(some(ty)) { ret ty; }
some(none) {
tcx.sess.span_fatal(ast_ty.span,
"illegal recursive type \
tcx.sess.span_fatal(ast_ty.span, "illegal recursive type. \
insert a enum in the cycle, \
if this is desired)");
}
@ -2490,7 +2489,7 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
demand::simple(fcx, e.span, declty, cty);
}
fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
id: ast::node_id) {
// FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression.
@ -2537,6 +2536,20 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
disr_vals += [disr_val];
disr_val += 1;
}
let outer = true, did = local_def(id);
if ty::type_structurally_contains(ccx.tcx, rty, {|sty|
alt sty {
ty::ty_enum(id, _) if id == did {
if outer { outer = false; false }
else { true }
}
_ { false }
}
}) {
ccx.tcx.sess.span_fatal(sp, "illegal recursive enum type. \
wrap the inner value in a box to \
make it represenable");
}
}
// A generic function for checking the pred in a check

View file

@ -0,0 +1,5 @@
// error-pattern: illegal recursive enum type
enum list<T> { cons(T, list<T>), nil }
fn main() {}