Fix ConstExpr::Other handling
diff --git a/src/constant.rs b/src/constant.rs
index d0f11b5..145729d 100644
--- a/src/constant.rs
+++ b/src/constant.rs
@@ -43,8 +43,6 @@
     use lit::parsing::lit;
     use op::parsing::{binop, unop};
     use ty::parsing::{path, ty};
-    #[cfg(feature = "full")] use expr::parsing::expr;
-    #[cfg(not(feature = "full"))] use synom::IResult;
 
     named!(pub const_expr -> ConstExpr, do_parse!(
         mut e: alt!(
@@ -55,8 +53,11 @@
             expr_path
             |
             expr_paren
-            |
-            expr_other
+            // Cannot handle ConstExpr::Other here because for example
+            // `[u32; n!()]` would end up successfully parsing `n` as
+            // ConstExpr::Path and then fail to parse `!()`. Instead, callers
+            // are required to handle Other. See ty::parsing::array_len and
+            // data::parsing::discriminant.
         ) >>
         many0!(alt!(
             tap!(args: and_call => {
@@ -98,14 +99,6 @@
 
     named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
 
-    #[cfg(feature = "full")]
-    named!(expr_other -> ConstExpr, map!(expr, ConstExpr::Other));
-
-    #[cfg(not(feature = "full"))]
-    fn expr_other(_: &str) -> IResult<&str, ConstExpr> {
-        IResult::Error
-    }
-
     named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
 
     named!(expr_paren -> ConstExpr, do_parse!(
diff --git a/src/data.rs b/src/data.rs
index 7ccfd7a..3b90b1f 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -54,8 +54,12 @@
 pub mod parsing {
     use super::*;
     use WhereClause;
+    #[cfg(feature = "full")]
+    use ConstExpr;
     use attr::parsing::outer_attr;
     use constant::parsing::const_expr;
+    #[cfg(feature = "full")]
+    use expr::parsing::expr;
     use generics::parsing::where_clause;
     use ident::parsing::ident;
     use ty::parsing::{path, ty};
@@ -99,7 +103,7 @@
             |
             epsilon!() => { |_| VariantData::Unit }
         ) >>
-        disr: option!(preceded!(punct!("="), const_expr)) >>
+        disr: option!(preceded!(punct!("="), discriminant)) >>
         (Variant {
             ident: id,
             attrs: attrs,
@@ -108,6 +112,19 @@
         })
     ));
 
+    #[cfg(not(feature = "full"))]
+    use self::const_expr as discriminant;
+
+    #[cfg(feature = "full")]
+    named!(discriminant -> ConstExpr, alt!(
+        terminated!(const_expr, after_discriminant)
+        |
+        terminated!(expr, after_discriminant) => { ConstExpr::Other }
+    ));
+
+    #[cfg(feature = "full")]
+    named!(after_discriminant -> &str, peek!(alt!(punct!(",") | punct!("}"))));
+
     named!(pub struct_like_body -> Vec<Field>, do_parse!(
         punct!("{") >>
         fields: terminated_list!(punct!(","), struct_field) >>
diff --git a/src/ty.rs b/src/ty.rs
index f0cc88c..efc5cca 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -278,29 +278,28 @@
         (Ty::Slice(Box::new(elem)))
     ));
 
-    #[cfg(not(feature = "full"))]
     named!(ty_array -> Ty, do_parse!(
         punct!("[") >>
         elem: ty >>
         punct!(";") >>
-        len: const_expr >>
+        len: array_len >>
         punct!("]") >>
         (Ty::Array(Box::new(elem), len))
     ));
 
+    #[cfg(not(feature = "full"))]
+    use self::const_expr as array_len;
+
     #[cfg(feature = "full")]
-    named!(ty_array -> Ty, do_parse!(
-        punct!("[") >>
-        elem: ty >>
-        punct!(";") >>
-        len: alt!(
-            terminated!(const_expr, punct!("]"))
-            |
-            terminated!(expr, punct!("]")) => { ConstExpr::Other }
-        ) >>
-        (Ty::Array(Box::new(elem), len))
+    named!(array_len -> ConstExpr, alt!(
+        terminated!(const_expr, after_array_len)
+        |
+        terminated!(expr, after_array_len) => { ConstExpr::Other }
     ));
 
+    #[cfg(feature = "full")]
+    named!(after_array_len -> &str, peek!(punct!("]")));
+
     named!(ty_ptr -> Ty, do_parse!(
         punct!("*") >>
         mutability: alt!(