1
Fork 0

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_unique;
export type_is_enum; export type_is_enum;
export type_is_c_like_enum; export type_is_c_like_enum;
export type_structurally_contains;
export type_structurally_contains_uniques; export type_structurally_contains_uniques;
export type_autoderef; export type_autoderef;
export type_param; export type_param;

View file

@ -259,10 +259,9 @@ 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) { alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
some(some(ty)) { ret ty; } some(some(ty)) { ret ty; }
some(none) { some(none) {
tcx.sess.span_fatal(ast_ty.span, tcx.sess.span_fatal(ast_ty.span, "illegal recursive type. \
"illegal recursive type \ insert a enum in the cycle, \
insert a enum in the cycle, \ if this is desired)");
if this is desired)");
} }
none { } none { }
} /* go on */ } /* go on */
@ -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); 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) { id: ast::node_id) {
// FIXME: this is kinda a kludge; we manufacture a fake function context // FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression. // and statement context for checking the initializer expression.
@ -2512,7 +2511,7 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
some(e) { some(e) {
check_expr(fcx, e); check_expr(fcx, e);
let cty = expr_ty(fcx.ccx.tcx, e); let cty = expr_ty(fcx.ccx.tcx, e);
let declty =ty::mk_int(fcx.ccx.tcx); let declty = ty::mk_int(fcx.ccx.tcx);
demand::simple(fcx, e.span, declty, cty); demand::simple(fcx, e.span, declty, cty);
// FIXME: issue #1417 // FIXME: issue #1417
// Also, check_expr (from check_const pass) doesn't guarantee that // Also, check_expr (from check_const pass) doesn't guarantee that
@ -2537,6 +2536,20 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
disr_vals += [disr_val]; disr_vals += [disr_val];
disr_val += 1; 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 // 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() {}