Compute enum discriminant during parsing

This allows us to reuse the computation in multiple places later.
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3c059a7..4e98674 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -367,12 +367,7 @@
     }
     writeln!(out, "enum class {} : uint32_t {{", enm.ident);
     for variant in &enm.variants {
-        write!(out, "  ");
-        write!(out, "{}", variant.ident);
-        if let Some(discriminant) = &variant.discriminant {
-            write!(out, " = {}", discriminant);
-        }
-        writeln!(out, ",");
+        writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
 }
@@ -383,18 +378,13 @@
         "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
         enm.ident
     );
-    let mut prev_discriminant = None;
     for variant in &enm.variants {
-        let discriminant = variant
-            .discriminant
-            .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
         writeln!(
             out,
             "static_assert(static_cast<uint32_t>({}::{}) == {},
               \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident, variant.ident, discriminant,
+            enm.ident, variant.ident, variant.discriminant,
         );
-        prev_discriminant = Some(discriminant);
     }
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d8810dc..fcb845c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -139,19 +139,13 @@
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
-    let variants = enm
-        .variants
-        .iter()
-        .scan(None, |prev_discriminant, variant| {
-            let variant_ident = &variant.ident;
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            *prev_discriminant = Some(discriminant);
-            Some(quote! {
-                pub const #variant_ident: Self = #ident { repr: #discriminant };
-            })
-        });
+    let variants = enm.variants.iter().map(|variant| {
+        let variant_ident = &variant.ident;
+        let discriminant = &variant.discriminant;
+        Some(quote! {
+            pub const #variant_ident: Self = #ident { repr: #discriminant };
+        })
+    });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
diff --git a/syntax/check.rs b/syntax/check.rs
index 72b4a6c..c54430c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -7,9 +7,7 @@
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
-use std::collections::HashSet;
 use std::fmt::Display;
-use std::u32;
 
 pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
@@ -191,25 +189,6 @@
         let span = span_for_enum_error(enm);
         cx.error(span, "enums without any variants are not supported");
     }
-
-    let mut discriminants = HashSet::new();
-    enm.variants
-        .iter()
-        .fold(None, |prev_discriminant, variant| {
-            if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
-                let msg = format!("overflowed on value after {}", prev_discriminant.unwrap());
-                cx.error(span_for_enum_error(enm), msg);
-                return None;
-            }
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            if !discriminants.insert(discriminant) {
-                let msg = format!("discriminant value `{}` already exists", discriminant);
-                cx.error(span_for_enum_error(enm), msg);
-            }
-            Some(discriminant)
-        });
 }
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e6c5bb8..fd8db73 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -95,7 +95,7 @@
 
 pub struct Variant {
     pub ident: Ident,
-    pub discriminant: Option<u32>,
+    pub discriminant: u32,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8bf0a4a..fc51ee9 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,6 +5,7 @@
     Struct, Ty1, Type, Var, Variant,
 };
 use quote::{format_ident, quote};
+use std::collections::HashSet;
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
@@ -96,16 +97,33 @@
 
     let doc = attrs::parse_doc(&item.attrs)?;
 
-    for variant in &item.variants {
-        match &variant.fields {
+    let mut variants = Vec::new();
+    let mut discriminants = HashSet::new();
+    let mut prev_discriminant = None;
+    for variant in item.variants {
+        match variant.fields {
             Fields::Unit => {}
             _ => {
                 return Err(Error::new_spanned(
                     variant,
                     "enums with data are not supported yet",
-                ))
+                ));
             }
         }
+        if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
+            return Err(Error::new_spanned(variant, "overflowed on value"));
+        }
+        let discriminant =
+            parse_discriminant(&variant)?.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+        if !discriminants.insert(discriminant) {
+            let msg = format!("discriminant value `{}` already exists", discriminant);
+            return Err(Error::new_spanned(variant, msg));
+        }
+        variants.push(Variant {
+            ident: variant.ident,
+            discriminant: discriminant,
+        });
+        prev_discriminant = Some(discriminant);
     }
 
     Ok(Api::Enum(Enum {
@@ -113,30 +131,20 @@
         enum_token: item.enum_token,
         ident: item.ident,
         brace_token: item.brace_token,
-        variants: item
-            .variants
-            .into_iter()
-            .map(parse_variant)
-            .collect::<Result<_>>()?,
+        variants: variants,
     }))
 }
 
-fn parse_variant(variant: RustVariant) -> Result<Variant> {
+fn parse_discriminant(variant: &RustVariant) -> Result<Option<u32>> {
     match &variant.discriminant {
-        None => Ok(Variant {
-            ident: variant.ident,
-            discriminant: None,
-        }),
+        None => Ok(None),
         Some((
             _,
             Expr::Lit(ExprLit {
                 lit: Lit::Int(n), ..
             }),
         )) => match n.base10_parse() {
-            Ok(val) => Ok(Variant {
-                ident: variant.ident,
-                discriminant: Some(val),
-            }),
+            Ok(val) => Ok(Some(val)),
             Err(_) => Err(Error::new_spanned(
                 variant,
                 "cannot parse enum discriminant as an integer",
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
index f5a879f..14505e3 100644
--- a/tests/ui/duplicate_enum_discriminants.stderr
+++ b/tests/ui/duplicate_enum_discriminants.stderr
@@ -1,18 +1,11 @@
 error: discriminant value `10` already exists
- --> $DIR/duplicate_enum_discriminants.rs:3:5
+ --> $DIR/duplicate_enum_discriminants.rs:5:9
   |
-3 | /     enum A {
-4 | |         V1 = 10,
-5 | |         V2 = 10,
-6 | |     }
-  | |_____^
+5 |         V2 = 10,
+  |         ^^^^^^^
 
 error: discriminant value `11` already exists
-  --> $DIR/duplicate_enum_discriminants.rs:8:5
+  --> $DIR/duplicate_enum_discriminants.rs:11:9
    |
-8  | /     enum B {
-9  | |         V1 = 10,
-10 | |         V2,
-11 | |         V3 = 11,
-12 | |     }
-   | |_____^
+11 |         V3 = 11,
+   |         ^^^^^^^
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
index 3d1b370..1a22146 100644
--- a/tests/ui/enum_overflows.stderr
+++ b/tests/ui/enum_overflows.stderr
@@ -1,9 +1,5 @@
-error: overflowed on value after 4294967295
-  --> $DIR/enum_overflows.rs:10:5
+error: overflowed on value
+  --> $DIR/enum_overflows.rs:13:9
    |
-10 | /     enum Bad {
-11 | |         D = 0xfffffffe,
-12 | |         E,
-13 | |         F,
-14 | |     }
-   | |_____^
+13 |         F,
+   |         ^