about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-01-27 16:01:04 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-01-27 16:03:43 +0100
commitdc55c06aa30a09f54e96e4049659fb1e3b85c486 (patch)
tree720b8a2426a1d9eb7fc2d00f87db5cf998d2d1fb
parent03e9dac09a737f47f1ce75b12826cebe320f2f77 (diff)
downloadrust-dc55c06aa30a09f54e96e4049659fb1e3b85c486.tar.gz
rust-dc55c06aa30a09f54e96e4049659fb1e3b85c486.zip
Properly check enum types for recursion
Closes #742
-rw-r--r--src/comp/middle/ty.rs1
-rw-r--r--src/comp/middle/typeck.rs25
-rw-r--r--src/test/compile-fail/recursive-enum.rs5
3 files changed, 25 insertions, 6 deletions
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 160bb832f13..944614ad03e 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -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;
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 1d54ec2befc..c1079466e73 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -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) {
       some(some(ty)) { ret ty; }
       some(none) {
-        tcx.sess.span_fatal(ast_ty.span,
-                            "illegal recursive type \
-                              insert a enum in the cycle, \
-                              if this is desired)");
+        tcx.sess.span_fatal(ast_ty.span, "illegal recursive type. \
+                                          insert a enum in the cycle, \
+                                          if this is desired)");
       }
       none { }
     } /* 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);
 }
 
-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.
@@ -2512,7 +2511,7 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
           some(e) {
             check_expr(fcx, 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);
             // FIXME: issue #1417
             // 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_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
diff --git a/src/test/compile-fail/recursive-enum.rs b/src/test/compile-fail/recursive-enum.rs
new file mode 100644
index 00000000000..b3764036b99
--- /dev/null
+++ b/src/test/compile-fail/recursive-enum.rs
@@ -0,0 +1,5 @@
+// error-pattern: illegal recursive enum type
+
+enum list<T> { cons(T, list<T>), nil }
+
+fn main() {}