Skip to content

Commit dc55c06

Browse files
committed
Properly check enum types for recursion
Closes #742
1 parent 03e9dac commit dc55c06

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

src/comp/middle/ty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export type_is_str;
172172
export type_is_unique;
173173
export type_is_enum;
174174
export type_is_c_like_enum;
175+
export type_structurally_contains;
175176
export type_structurally_contains_uniques;
176177
export type_autoderef;
177178
export type_param;

src/comp/middle/typeck.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
259259
alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
260260
some(some(ty)) { ret ty; }
261261
some(none) {
262-
tcx.sess.span_fatal(ast_ty.span,
263-
"illegal recursive type \
264-
insert a enum in the cycle, \
265-
if this is desired)");
262+
tcx.sess.span_fatal(ast_ty.span, "illegal recursive type. \
263+
insert a enum in the cycle, \
264+
if this is desired)");
266265
}
267266
none { }
268267
} /* go on */
@@ -2490,7 +2489,7 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
24902489
demand::simple(fcx, e.span, declty, cty);
24912490
}
24922491

2493-
fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
2492+
fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
24942493
id: ast::node_id) {
24952494
// FIXME: this is kinda a kludge; we manufacture a fake function context
24962495
// and statement context for checking the initializer expression.
@@ -2512,7 +2511,7 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
25122511
some(e) {
25132512
check_expr(fcx, e);
25142513
let cty = expr_ty(fcx.ccx.tcx, e);
2515-
let declty =ty::mk_int(fcx.ccx.tcx);
2514+
let declty = ty::mk_int(fcx.ccx.tcx);
25162515
demand::simple(fcx, e.span, declty, cty);
25172516
// FIXME: issue #1417
25182517
// 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],
25372536
disr_vals += [disr_val];
25382537
disr_val += 1;
25392538
}
2539+
let outer = true, did = local_def(id);
2540+
if ty::type_structurally_contains(ccx.tcx, rty, {|sty|
2541+
alt sty {
2542+
ty::ty_enum(id, _) if id == did {
2543+
if outer { outer = false; false }
2544+
else { true }
2545+
}
2546+
_ { false }
2547+
}
2548+
}) {
2549+
ccx.tcx.sess.span_fatal(sp, "illegal recursive enum type. \
2550+
wrap the inner value in a box to \
2551+
make it represenable");
2552+
}
25402553
}
25412554

25422555
// A generic function for checking the pred in a check
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// error-pattern: illegal recursive enum type
2+
3+
enum list<T> { cons(T, list<T>), nil }
4+
5+
fn main() {}

0 commit comments

Comments
 (0)