]> git.lizzy.rs Git - rust.git/commitdiff
rustc: move the actual values of enum discriminants into a map.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Sun, 5 Feb 2017 05:01:48 +0000 (07:01 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Sat, 25 Feb 2017 15:07:59 +0000 (17:07 +0200)
23 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/mir/tcx.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_const_math/int.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/matches/test.rs
src/librustc_trans/callee.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/disr.rs
src/librustc_trans/glue.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/test/compile-fail/E0081.rs
src/test/compile-fail/issue-15524.rs

index 96d1a925425e8d322a283e9bc4ffc6a716b1eb52..8da032f59353a9ea0410aca3e1b63331bf8f0910 100644 (file)
@@ -114,6 +114,7 @@ pub enum DepNode<D: Clone + Debug> {
     InherentImpls(D),
     TypeckTables(D),
     UsedTraitImports(D),
+    MonomorphicConstEval(D),
 
     // The set of impls for a given trait. Ultimately, it would be
     // nice to get more fine-grained here (e.g., to include a
@@ -263,6 +264,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             InherentImpls(ref d) => op(d).map(InherentImpls),
             TypeckTables(ref d) => op(d).map(TypeckTables),
             UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
+            MonomorphicConstEval(ref d) => op(d).map(MonomorphicConstEval),
             TraitImpls(ref d) => op(d).map(TraitImpls),
             TraitItems(ref d) => op(d).map(TraitItems),
             ReprHints(ref d) => op(d).map(ReprHints),
index 5c8d031caf60dafc365bcba535d7fb41a204b4fe..527f115277082318de059d8be2a4d4cf47712b17 100644 (file)
@@ -173,7 +173,9 @@ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Opti
             Rvalue::Discriminant(ref lval) => {
                 let ty = lval.ty(mir, tcx).to_ty(tcx);
                 if let ty::TyAdt(adt_def, _) = ty.sty {
-                    Some(adt_def.discr_ty.to_ty(tcx))
+                    let repr_hints = tcx.lookup_repr_hints(adt_def.did);
+                    let repr_type = tcx.enum_repr_type(repr_hints.get(0));
+                    Some(repr_type.to_ty(tcx))
                 } else {
                     // Undefined behaviour, bug for now; may want to return something for
                     // the `discriminant` intrinsic later.
index 2f062e2e5b19454e4b6241b39700627ec7ba0219..c7e7fac275981eb77386b9b605e360f625f82476 100644 (file)
@@ -507,6 +507,10 @@ pub struct GlobalCtxt<'tcx> {
     /// FIXME(arielb1): why is this separate from populated_external_types?
     pub populated_external_primitive_impls: RefCell<DefIdSet>,
 
+    /// Results of evaluating monomorphic constants embedded in
+    /// other items, such as enum variant explicit discriminants.
+    pub monomorphic_const_eval: RefCell<DepTrackingMap<maps::MonomorphicConstEval<'tcx>>>,
+
     /// Maps any item's def-id to its stability index.
     pub stability: RefCell<stability::Index<'tcx>>,
 
@@ -662,12 +666,10 @@ pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
     pub fn alloc_adt_def(self,
                          did: DefId,
                          kind: AdtKind,
-                         discr_ty: Option<attr::IntType>,
                          variants: Vec<ty::VariantDef>,
                          repr: ReprOptions)
                          -> &'gcx ty::AdtDef {
-        let discr_ty = discr_ty.unwrap_or(attr::UnsignedInt(ast::UintTy::U8));
-        let def = ty::AdtDef::new(self, did, kind, discr_ty, variants, repr);
+        let def = ty::AdtDef::new(self, did, kind, variants, repr);
         self.global_arenas.adt_def.alloc(def)
     }
 
@@ -783,6 +785,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             populated_external_types: RefCell::new(DefIdSet()),
             populated_external_primitive_impls: RefCell::new(DefIdSet()),
+            monomorphic_const_eval: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             stability: RefCell::new(stability),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
index f429053d8bb1223a782cddd013c95b8bb766baef..5829ae195c9413bd5acfe7fd6b3669b3e14eb66d 100644 (file)
@@ -20,6 +20,7 @@
 use syntax::ast::{FloatTy, IntTy, UintTy};
 use syntax::attr;
 use syntax_pos::DUMMY_SP;
+use rustc_const_math::ConstInt;
 
 use std::cmp;
 use std::fmt;
@@ -1181,8 +1182,12 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     let (mut min, mut max, mut non_zero) = (i64::max_value(),
                                                             i64::min_value(),
                                                             true);
-                    for v in &def.variants {
-                        let x = v.disr_val as i128 as i64;
+                    for discr in def.discriminants(tcx) {
+                        let x = match discr.erase_type() {
+                            ConstInt::InferSigned(i) => i as i64,
+                            ConstInt::Infer(i) => i as u64 as i64,
+                            _ => bug!()
+                        };
                         if x == 0 { non_zero = false; }
                         if x < min { min = x; }
                         if x > max { max = x; }
@@ -1240,7 +1245,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                 // non-empty body, explicit discriminants should have
                 // been rejected by a checker before this point.
                 for (i, v) in def.variants.iter().enumerate() {
-                    if i as u128 != v.disr_val {
+                    if v.discr != ty::VariantDiscr::Relative(i) {
                         bug!("non-C-like enum {} with specified discriminants",
                             tcx.item_path_str(def.did));
                     }
@@ -1348,7 +1353,9 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     return Err(LayoutError::SizeOverflow(ty));
                 }
 
-                let typeck_ity = Integer::from_attr(dl, def.discr_ty);
+                let repr_hints = tcx.lookup_repr_hints(def.did);
+                let repr_type = tcx.enum_repr_type(repr_hints.get(0));
+                let typeck_ity = Integer::from_attr(dl, repr_type);
                 if typeck_ity < min_ity {
                     // It is a bug if Layout decided on a greater discriminant size than typeck for
                     // some reason at this point (based on values discriminant can take on). Mostly
index d2c237d5db61dfaf56a50169bd7f0a58771d13c0..cedb0307495602696a47053091d62e3fe9a5ccce 100644 (file)
@@ -10,6 +10,7 @@
 
 use dep_graph::{DepNode, DepTrackingMapConfig};
 use hir::def_id::DefId;
+use middle::const_val::ConstVal;
 use mir;
 use ty::{self, Ty};
 use util::nodemap::DefIdSet;
@@ -51,3 +52,4 @@ fn to_dep_node(key: &$key) -> DepNode<DefId> { DepNode::$node_name(*key) }
 dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
 dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> }
 dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet }
+dep_map_ty! { MonomorphicConstEval: MonomorphicConstEval(DefId) -> Result<ConstVal, ()> }
index 1275530b1bdf91016060ba23a591de0d37354d25..be4ec881482d1870957c50a241fdf996a24440de 100644 (file)
@@ -20,6 +20,7 @@
 use middle;
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
 use middle::resolve_lifetime::ObjectLifetimeDefault;
@@ -27,6 +28,7 @@
 use traits;
 use ty;
 use ty::subst::{Subst, Substs};
+use ty::util::IntTypeExt;
 use ty::walk::TypeWalker;
 use util::common::MemoizationMap;
 use util::nodemap::{NodeSet, NodeMap, FxHashMap};
@@ -45,6 +47,7 @@
 use syntax::attr;
 use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
+use rustc_const_math::ConstInt;
 
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
 
@@ -96,8 +99,6 @@
 mod structural_impls;
 mod sty;
 
-pub type Disr = u128;
-
 // Data types
 
 /// The complete set of all analyses described in this module. This is
@@ -1309,11 +1310,24 @@ pub struct VariantDef {
     /// this is the DefId of the struct's ctor.
     pub did: DefId,
     pub name: Name, // struct's name if this is a struct
-    pub disr_val: Disr,
+    pub discr: VariantDiscr,
     pub fields: Vec<FieldDef>,
     pub ctor_kind: CtorKind,
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+pub enum VariantDiscr {
+    /// Explicit value for this variant, i.e. `X = 123`.
+    /// The `DefId` corresponds to the embedded constant.
+    Explicit(DefId),
+
+    /// The previous variant's discriminant plus one.
+    /// For efficiency reasons, the distance from the
+    /// last `Explicit` discriminant is being stored,
+    /// or `0` for the first variant, if it has none.
+    Relative(usize),
+}
+
 #[derive(Debug)]
 pub struct FieldDef {
     pub did: DefId,
@@ -1327,12 +1341,6 @@ pub struct FieldDef {
 /// table.
 pub struct AdtDef {
     pub did: DefId,
-    /// Type of the discriminant
-    ///
-    /// Note, that this is the type specified in `repr()` or a default type of some sort, and might
-    /// not match the actual type that layout algorithm decides to use when translating this type
-    /// into LLVM. That being said, layout algorithm may not use a type larger than specified here.
-    pub discr_ty: attr::IntType,
     pub variants: Vec<VariantDef>,
     destructor: Cell<Option<DefId>>,
     flags: Cell<AdtFlags>,
@@ -1395,7 +1403,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
            did: DefId,
            kind: AdtKind,
-           discr_ty: attr::IntType,
            variants: Vec<VariantDef>,
            repr: ReprOptions) -> Self {
         let mut flags = AdtFlags::NO_ADT_FLAGS;
@@ -1419,7 +1426,6 @@ fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         }
         AdtDef {
             did: did,
-            discr_ty: discr_ty,
             variants: variants,
             flags: Cell::new(flags),
             destructor: Cell::new(None),
@@ -1577,6 +1583,28 @@ pub fn set_destructor(&self, dtor: DefId) {
         self.destructor.set(Some(dtor));
     }
 
+    pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+                         -> impl Iterator<Item=ConstInt> + 'a {
+        let repr_hints = tcx.lookup_repr_hints(self.did);
+        let repr_type = tcx.enum_repr_type(repr_hints.get(0));
+        let initial = repr_type.initial_discriminant(tcx.global_tcx());
+        let mut prev_discr = None::<ConstInt>;
+        self.variants.iter().map(move |v| {
+            let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
+            if let VariantDiscr::Explicit(expr_did) = v.discr {
+                match tcx.monomorphic_const_eval.borrow()[&expr_did] {
+                    Ok(ConstVal::Integral(v)) => {
+                        discr = v;
+                    }
+                    _ => {}
+                }
+            }
+            prev_discr = Some(discr);
+
+            discr
+        })
+    }
+
     /// Returns a simpler type such that `Self: Sized` if and only
     /// if that type is Sized, or `TyErr` if this type is recursive.
     ///
index 16492de6c3d27fefb456f787c89a8a876628877e..af25990978793696c2b9a0245e54af584a892d85 100644 (file)
 use hir::map as hir_map;
 use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
-use ty::{Disr, ParameterEnvironment};
+use ty::{ParameterEnvironment};
 use ty::fold::TypeVisitor;
 use ty::layout::{Layout, LayoutError};
 use ty::TypeVariants::*;
 use util::nodemap::FxHashMap;
 use middle::lang_items;
 
+use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult};
 
 use std::cell::RefCell;
 
 use hir;
 
-pub trait IntTypeExt {
-    fn to_ty<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>;
-    fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr;
-}
+type Disr = ConstInt;
+
+ pub trait IntTypeExt {
+    fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>;
+    fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
+                           -> Option<Disr>;
+    fn assert_ty_matches(&self, val: Disr);
+    fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr;
+ }
+
 
 impl IntTypeExt for attr::IntType {
-    fn to_ty<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        match self {
-            SignedInt(i) => tcx.mk_mach_int(i),
-            UnsignedInt(i) => tcx.mk_mach_uint(i),
+    fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
+        match *self {
+            SignedInt(ast::IntTy::I8)      => tcx.types.i8,
+            SignedInt(ast::IntTy::I16)     => tcx.types.i16,
+            SignedInt(ast::IntTy::I32)     => tcx.types.i32,
+            SignedInt(ast::IntTy::I64)     => tcx.types.i64,
+            SignedInt(ast::IntTy::I128)     => tcx.types.i128,
+            SignedInt(ast::IntTy::Is)   => tcx.types.isize,
+            UnsignedInt(ast::UintTy::U8)    => tcx.types.u8,
+            UnsignedInt(ast::UintTy::U16)   => tcx.types.u16,
+            UnsignedInt(ast::UintTy::U32)   => tcx.types.u32,
+            UnsignedInt(ast::UintTy::U64)   => tcx.types.u64,
+            UnsignedInt(ast::UintTy::U128)   => tcx.types.u128,
+            UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
+        }
+    }
+
+    fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
+        match *self {
+            SignedInt(ast::IntTy::I8)    => ConstInt::I8(0),
+            SignedInt(ast::IntTy::I16)   => ConstInt::I16(0),
+            SignedInt(ast::IntTy::I32)   => ConstInt::I32(0),
+            SignedInt(ast::IntTy::I64)   => ConstInt::I64(0),
+            SignedInt(ast::IntTy::I128)   => ConstInt::I128(0),
+            SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
+                ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)),
+                ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
+                ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)),
+                _ => bug!(),
+            },
+            UnsignedInt(ast::UintTy::U8)  => ConstInt::U8(0),
+            UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
+            UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
+            UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
+            UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0),
+            UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
+                ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)),
+                ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
+                ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)),
+                _ => bug!(),
+            },
         }
     }
 
-    fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
-        0
+    fn assert_ty_matches(&self, val: Disr) {
+        match (*self, val) {
+            (SignedInt(ast::IntTy::I8), ConstInt::I8(_)) => {},
+            (SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {},
+            (SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
+            (SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
+            (SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
+            (SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
+            (UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
+            (UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
+            (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
+            (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
+            (UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
+            (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
+            _ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
+        }
+    }
+
+    fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
+                           -> Option<Disr> {
+        if let Some(val) = val {
+            self.assert_ty_matches(val);
+            (val + ConstInt::Infer(1)).ok()
+        } else {
+            Some(self.initial_discriminant(tcx))
+        }
     }
 }
 
index 5899c9f31d14dc4c4d00c73a2183a37db193b566..c64b25032c9efbc59e11edf12f59724e90af17f7 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
 use rustc::mir::transform::{Pass, MirPass, MirSource};
-use rustc::middle::const_val::{ConstVal, ConstInt};
+use rustc::middle::const_val::ConstVal;
 use rustc::middle::lang_items;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -639,10 +639,7 @@ fn open_drop_for_adt<'a>(&mut self, c: &DropCtxt<'a, 'tcx>,
                 let mut values = Vec::with_capacity(adt.variants.len());
                 let mut blocks = Vec::with_capacity(adt.variants.len());
                 let mut otherwise = None;
-                for (variant_index, variant) in adt.variants.iter().enumerate() {
-                    let discr = ConstInt::new_inttype(variant.disr_val, adt.discr_ty,
-                                                      self.tcx.sess.target.uint_type,
-                                                      self.tcx.sess.target.int_type).unwrap();
+                for (variant_index, discr) in adt.discriminants(self.tcx).enumerate() {
                     let subpath = super::move_path_children_matching(
                         self.move_data(), c.path, |proj| match proj {
                             &Projection {
@@ -680,7 +677,9 @@ fn open_drop_for_adt<'a>(&mut self, c: &DropCtxt<'a, 'tcx>,
                 // Additionally, we do not want to switch on the
                 // discriminant after it is free-ed, because that
                 // way lies only trouble.
-                let discr_ty = adt.discr_ty.to_ty(self.tcx);
+                let repr_hints = self.tcx.lookup_repr_hints(adt.did);
+                let repr_type = self.tcx.enum_repr_type(repr_hints.get(0));
+                let discr_ty = repr_type.to_ty(self.tcx);
                 let discr = Lvalue::Local(self.patch.new_temp(discr_ty));
                 let switch_block = self.patch.new_block(BasicBlockData {
                     statements: vec![
index bc3809db1c63a619086b78b41daceb2d84a80ead..17714f2fb2d6cd3074c460e7b6783cbdf0704ee8 100644 (file)
@@ -77,14 +77,6 @@ mod ibounds {
 }
 
 impl ConstInt {
-    pub fn new_inttype(val: u128, ty: IntType, usize_ty: UintTy, isize_ty: IntTy)
-    -> Option<ConstInt> {
-        match ty {
-            IntType::SignedInt(i) => ConstInt::new_signed(val as i128, i, isize_ty),
-            IntType::UnsignedInt(i) => ConstInt::new_unsigned(val, i, usize_ty),
-        }
-    }
-
     /// Creates a new unsigned ConstInt with matching type while also checking that overflow does
     /// not happen.
     pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
index 22fa9411cc1172586beb0d15cb1d60f420bff63e..88b06e29e103ce3a0e7f00dc7cea166e7f1683b7 100644 (file)
@@ -515,7 +515,8 @@ pub fn get_trait_def(&self,
 
     fn get_variant(&self,
                    item: &Entry<'tcx>,
-                   index: DefIndex)
+                   index: DefIndex,
+                   tcx: TyCtxt<'a, 'tcx, 'tcx>)
                    -> (ty::VariantDef, Option<DefIndex>) {
         let data = match item.kind {
             EntryKind::Variant(data) |
@@ -524,6 +525,11 @@ fn get_variant(&self,
             _ => bug!(),
         };
 
+        if let ty::VariantDiscr::Explicit(def_id) = data.discr {
+            let result = data.evaluated_discr.map_or(Err(()), Ok);
+            tcx.monomorphic_const_eval.borrow_mut().insert(def_id, result);
+        }
+
         (ty::VariantDef {
             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
             name: self.item_name(index),
@@ -535,7 +541,7 @@ fn get_variant(&self,
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
-            disr_val: data.disr,
+            discr: data.discr,
             ctor_kind: data.ctor_kind,
         }, data.struct_ctor)
     }
@@ -546,10 +552,10 @@ pub fn get_adt_def(&self,
                        -> &'tcx ty::AdtDef {
         let item = self.entry(item_id);
         let did = self.local_def_id(item_id);
-        let (kind, ty) = match item.kind {
-            EntryKind::Enum(dt, _) => (ty::AdtKind::Enum, Some(dt.decode(self))),
-            EntryKind::Struct(_, _) => (ty::AdtKind::Struct, None),
-            EntryKind::Union(_, _) => (ty::AdtKind::Union, None),
+        let kind = match item.kind {
+            EntryKind::Enum(_) => ty::AdtKind::Enum,
+            EntryKind::Struct(_, _) => ty::AdtKind::Struct,
+            EntryKind::Union(_, _) => ty::AdtKind::Union,
             _ => bug!("get_adt_def called on a non-ADT {:?}", did),
         };
         let mut ctor_index = None;
@@ -557,24 +563,25 @@ pub fn get_adt_def(&self,
             item.children
                 .decode(self)
                 .map(|index| {
-                    let (variant, struct_ctor) = self.get_variant(&self.entry(index), index);
+                    let (variant, struct_ctor) =
+                        self.get_variant(&self.entry(index), index, tcx);
                     assert_eq!(struct_ctor, None);
                     variant
                 })
                 .collect()
         } else {
-            let (variant, struct_ctor) = self.get_variant(&item, item_id);
+            let (variant, struct_ctor) = self.get_variant(&item, item_id, tcx);
             ctor_index = struct_ctor;
             vec![variant]
         };
         let (kind, repr) = match item.kind {
-            EntryKind::Enum(_, repr) => (ty::AdtKind::Enum, repr),
+            EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
             EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
             EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
             _ => bug!("get_adt_def called on a non-ADT {:?}", did),
         };
 
-        let adt = tcx.alloc_adt_def(did, kind, ty, variants, repr);
+        let adt = tcx.alloc_adt_def(did, kind, variants, repr);
         if let Some(ctor_index) = ctor_index {
             // Make adt definition available through constructor id as well.
             tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt);
index a643ed59af136d4e68520fe910c8359836b8325d..725d54c227a3074a3864f94b2e3aece2207b0c39 100644 (file)
@@ -261,7 +261,13 @@ fn encode_enum_variant_info(&mut self,
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
-            disr: variant.disr_val,
+            discr: variant.discr,
+            evaluated_discr: match variant.discr {
+                ty::VariantDiscr::Explicit(def_id) => {
+                    tcx.monomorphic_const_eval.borrow()[&def_id].clone().ok()
+                }
+                ty::VariantDiscr::Relative(_) => None
+            },
             struct_ctor: None,
         };
 
@@ -388,7 +394,8 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
-            disr: variant.disr_val,
+            discr: variant.discr,
+            evaluated_discr: None,
             struct_ctor: Some(def_id.index),
         };
 
@@ -644,8 +651,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             }
             hir::ItemForeignMod(_) => EntryKind::ForeignMod,
             hir::ItemTy(..) => EntryKind::Type,
-            hir::ItemEnum(..) => EntryKind::Enum(self.lazy(&tcx.lookup_adt_def(def_id).discr_ty),
-                                                 get_repr_options(&tcx, def_id)),
+            hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
             hir::ItemStruct(ref struct_def, _) => {
                 let variant = tcx.lookup_adt_def(def_id).struct_variant();
 
@@ -662,7 +668,8 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
 
                 EntryKind::Struct(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
-                    disr: variant.disr_val,
+                    discr: variant.discr,
+                    evaluated_discr: None,
                     struct_ctor: struct_ctor,
                 }), repr_options)
             }
@@ -672,7 +679,8 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
 
                 EntryKind::Union(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
-                    disr: variant.disr_val,
+                    discr: variant.discr,
+                    evaluated_discr: None,
                     struct_ctor: None,
                 }), repr_options)
             }
index ee30063fcbd06f9e3bb14e68ebb8b67941202f47..6307d4eda308efd24256fd8af000b94c2a43f389 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::hir;
 use rustc::hir::def::{self, CtorKind};
 use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::middle::const_val::ConstVal;
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
 use rustc::middle::lang_items;
 use rustc::mir;
@@ -227,7 +228,7 @@ pub enum EntryKind<'tcx> {
     ForeignMutStatic,
     ForeignMod,
     Type,
-    Enum(Lazy<attr::IntType>, ReprOptions),
+    Enum(ReprOptions),
     Field,
     Variant(Lazy<VariantData>),
     Struct(Lazy<VariantData>, ReprOptions),
@@ -264,7 +265,8 @@ pub struct FnData {
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct VariantData {
     pub ctor_kind: CtorKind,
-    pub disr: u128,
+    pub discr: ty::VariantDiscr,
+    pub evaluated_discr: Option<ConstVal>,
 
     /// If this is a struct's only variant, this
     /// is the index of the "struct ctor" item.
index 01c0433112bf33aa1edd2929d187bc1564ed9e14..3256bdf9c25e31ae30d84ebfa99de0cfb4cdca48 100644 (file)
@@ -20,7 +20,7 @@
 use hair::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::bitvec::BitVector;
-use rustc::middle::const_val::{ConstVal, ConstInt};
+use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
@@ -191,11 +191,8 @@ pub fn perform_test(&mut self,
                 let mut targets = Vec::with_capacity(used_variants + 1);
                 let mut values = Vec::with_capacity(used_variants);
                 let tcx = self.hir.tcx();
-                for (idx, variant) in adt_def.variants.iter().enumerate() {
+                for (idx, discr) in adt_def.discriminants(tcx).enumerate() {
                     target_blocks.place_back() <- if variants.contains(idx) {
-                        let discr = ConstInt::new_inttype(variant.disr_val, adt_def.discr_ty,
-                                                          tcx.sess.target.uint_type,
-                                                          tcx.sess.target.int_type).unwrap();
                         values.push(discr);
                         *(targets.place_back() <- self.cfg.start_new_block())
                     } else {
@@ -212,7 +209,9 @@ pub fn perform_test(&mut self,
                 }
                 debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}",
                        num_enum_variants, values, variants);
-                let discr_ty = adt_def.discr_ty.to_ty(tcx);
+                let repr_hints = tcx.lookup_repr_hints(adt_def.did);
+                let repr_type = tcx.enum_repr_type(repr_hints.get(0));
+                let discr_ty = repr_type.to_ty(tcx);
                 let discr = self.temp(discr_ty);
                 self.cfg.push_assign(block, source_info, &discr,
                                      Rvalue::Discriminant(lvalue.clone()));
index 4a8658dd2e308a86d2bec71d3c0a890102c6979a..9a06820115f632831d152dbaade69007082b83c7 100644 (file)
@@ -93,9 +93,9 @@ pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs
 
         // FIXME(eddyb) Detect ADT constructors more efficiently.
         if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
-            if let Some(v) = adt_def.variants.iter().find(|v| def_id == v.did) {
+            if let Some(i) = adt_def.variants.iter().position(|v| def_id == v.did) {
                 return Callee {
-                    data: NamedTupleConstructor(Disr::from(v.disr_val)),
+                    data: NamedTupleConstructor(Disr::for_variant(tcx, adt_def, i)),
                     ty: fn_ty
                 };
             }
index 11c0bf852f727ac829d734d6e13db7f0ed7f97cf..2b584344ed1c7a3d9cb04e61dcf22e1ba2f786b3 100644 (file)
@@ -1465,10 +1465,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     // <unknown>
     let file_metadata = unknown_file_metadata(cx);
 
-    let variants = &enum_type.ty_adt_def().unwrap().variants;
-    let enumerators_metadata: Vec<DIDescriptor> = variants
-        .iter()
-        .map(|v| {
+    let def = enum_type.ty_adt_def().unwrap();
+    let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx())
+        .zip(&def.variants)
+        .map(|(discr, v)| {
             let token = v.name.as_str();
             let name = CString::new(token.as_bytes()).unwrap();
             unsafe {
@@ -1476,7 +1476,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     DIB(cx),
                     name.as_ptr(),
                     // FIXME: what if enumeration has i128 discriminant?
-                    v.disr_val as u64)
+                    discr.to_u128_unchecked() as u64)
             }
         })
         .collect();
index f3a62bc85b8d93252c441c43ca62f63e9ab0e24e..00c0e0d541586eeb92dc4f8f9d23ce26f967b342 100644 (file)
@@ -8,10 +8,42 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::middle::const_val::ConstVal;
+use rustc::ty::{self, TyCtxt};
+use rustc_const_math::ConstInt;
+
 #[derive(Debug, Eq, PartialEq, Copy, Clone)]
 pub struct Disr(pub u64);
 
 impl Disr {
+    pub fn for_variant(tcx: TyCtxt,
+                       def: &ty::AdtDef,
+                       variant_index: usize) -> Self {
+        let mut explicit_index = variant_index;
+        let mut explicit_value = Disr(0);
+        loop {
+            match def.variants[explicit_index].discr {
+                ty::VariantDiscr::Relative(0) => break,
+                ty::VariantDiscr::Relative(distance) => {
+                    explicit_index -= distance;
+                }
+                ty::VariantDiscr::Explicit(expr_did) => {
+                    match tcx.monomorphic_const_eval.borrow()[&expr_did] {
+                        Ok(ConstVal::Integral(v)) => {
+                            explicit_value = Disr::from(v);
+                            break;
+                        }
+                        _ => {
+                            explicit_index -= 1;
+                        }
+                    }
+                }
+            }
+        }
+        let distance = variant_index - explicit_index;
+        explicit_value.wrapping_add(Disr::from(distance))
+    }
+
     pub fn wrapping_add(self, other: Self) -> Self {
         Disr(self.0.wrapping_add(other.0))
     }
@@ -24,10 +56,10 @@ fn bitand(self, other: Self) -> Self {
     }
 }
 
-impl From<::rustc::ty::Disr> for Disr {
-    fn from(i: ::rustc::ty::Disr) -> Disr {
+impl From<ConstInt> for Disr {
+    fn from(i: ConstInt) -> Disr {
         // FIXME: what if discr has 128 bit discr?
-        Disr(i as u64)
+        Disr(i.to_u128_unchecked() as u64)
     }
 }
 
index 9963514acd73619b0b939b488e03d0a7fe16bf87..58e0a9e589f3369b70be642435d2088f85237195 100644 (file)
@@ -521,11 +521,10 @@ fn iter_variant_fields<'a, 'tcx>(
                         let llswitch = cx.switch(lldiscrim_a, ret_void_cx.llbb(), n_variants);
                         let next_cx = cx.build_sibling_block("enum-iter-next");
 
-                        for (i, variant) in adt.variants.iter().enumerate() {
-                            let variant_cx_name = format!("enum-iter-variant-{}",
-                                &variant.disr_val.to_string());
+                        for (i, discr) in adt.discriminants(cx.tcx()).enumerate() {
+                            let variant_cx_name = format!("enum-iter-variant-{}", i);
                             let variant_cx = cx.build_sibling_block(&variant_cx_name);
-                            let case_val = adt::trans_case(&cx, t, Disr::from(variant.disr_val));
+                            let case_val = adt::trans_case(&cx, t, Disr::from(discr));
                             variant_cx.add_case(llswitch, case_val, variant_cx.llbb());
                             ptr.ty = LvalueTy::Downcast {
                                 adt_def: adt,
index e6cae2f9f3296dba5297a733f11012105762a627..6a0e05803c355cef9d45b46dd3157e198a8f56ee 100644 (file)
@@ -1001,7 +1001,7 @@ fn trans_const<'a, 'tcx>(
         layout::CEnum { discr: d, min, max, .. } => {
             let discr = match *kind {
                 mir::AggregateKind::Adt(adt_def, _, _, _) => {
-                    Disr::from(adt_def.variants[variant_index].disr_val)
+                    Disr::for_variant(ccx.tcx(), adt_def, variant_index)
                 },
                 _ => Disr(0),
             };
index 6f6d81a25350fe229c20c891c3c4ad4f6b319d49..c3dffd476e133115308aacf397c8b59dc910011e 100644 (file)
@@ -106,9 +106,9 @@ pub fn trans_rvalue(&mut self,
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
                 match *kind {
                     mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
-                        let disr = Disr::from(adt_def.variants[variant_index].disr_val);
+                        let disr = Disr::for_variant(bcx.tcx(), adt_def, variant_index);
                         let dest_ty = dest.ty.to_ty(bcx.tcx());
-                        adt::trans_set_discr(&bcx, dest_ty, dest.llval, Disr::from(disr));
+                        adt::trans_set_discr(&bcx, dest_ty, dest.llval, disr);
                         for (i, operand) in operands.iter().enumerate() {
                             let op = self.trans_operand(&bcx, operand);
                             // Do not generate stores and GEPis for zero-sized fields.
@@ -119,7 +119,7 @@ pub fn trans_rvalue(&mut self,
                                 val.ty = LvalueTy::Downcast {
                                     adt_def: adt_def,
                                     substs: self.monomorphize(&substs),
-                                    variant_index: disr.0 as usize,
+                                    variant_index: variant_index,
                                 };
                                 let (lldest_i, align) = val.trans_field_ptr(&bcx, field_index);
                                 self.store_operand(&bcx, lldest_i, align.to_align(), op);
index d4895d638ba0d2fbab3d024aa70dfe25cdcf7ea8..6a003ef734020fecb1be85d4150233bac2d4bf86 100644 (file)
 use rustc::middle::lang_items;
 use rustc_back::slice;
 use rustc_const_eval::eval_length;
+use rustc_const_math::ConstInt;
 
 mod assoc;
 mod autoderef;
@@ -1323,14 +1324,12 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
     let def_id = ccx.tcx.hir.local_def_id(id);
 
-    let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
-    let mut disr_vals: Vec<ty::Disr> = Vec::new();
-    for (v, variant) in vs.iter().zip(variants.iter()) {
-        let current_disr_val = variant.disr_val;
-
+    let def = ccx.tcx.lookup_adt_def(def_id);
+    let mut disr_vals: Vec<ConstInt> = Vec::new();
+    for (discr, v) in def.discriminants(ccx.tcx).zip(vs) {
         // Check for duplicate discriminant values
-        if let Some(i) = disr_vals.iter().position(|&x| x == current_disr_val) {
-            let variant_i_node_id = ccx.tcx.hir.as_local_node_id(variants[i].did).unwrap();
+        if let Some(i) = disr_vals.iter().position(|&x| x == discr) {
+            let variant_i_node_id = ccx.tcx.hir.as_local_node_id(def.variants[i].did).unwrap();
             let variant_i = ccx.tcx.hir.expect_variant(variant_i_node_id);
             let i_span = match variant_i.node.disr_expr {
                 Some(expr) => ccx.tcx.hir.span(expr.node_id),
@@ -1346,7 +1345,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 .span_label(span , &format!("enum already has `{}`", disr_vals[i]))
                 .emit();
         }
-        disr_vals.push(current_disr_val);
+        disr_vals.push(discr);
     }
 
     check_representable(ccx.tcx, sp, def_id);
index 975a9aa994624846e12226af2a51a18a6a0538ff..3f3fc40320eb63903856501d531eba20b938e0de 100644 (file)
@@ -875,8 +875,36 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                         def: &'tcx ty::AdtDef,
                                         ty: Ty<'tcx>,
                                         variants: &[hir::Variant]) {
-    // fill the field types
+    let tcx = ccx.tcx;
+    let repr_hints = tcx.lookup_repr_hints(def.did);
+    let repr_type = tcx.enum_repr_type(repr_hints.get(0));
+    let initial = repr_type.initial_discriminant(tcx);
+    let mut prev_discr = None::<ConstInt>;
+
+    // fill the discriminant values and field types
     for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) {
+        let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr());
+        prev_discr = Some(if let Some(e) = variant.node.disr_expr {
+            let result = evaluate_disr_expr(ccx, repr_type, e);
+
+            let expr_did = tcx.hir.local_def_id(e.node_id);
+            tcx.monomorphic_const_eval.borrow_mut()
+               .insert(expr_did, result.map(ConstVal::Integral));
+
+            result.ok()
+        } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
+            Some(discr)
+        } else {
+            struct_span_err!(tcx.sess, variant.span, E0370,
+                             "enum discriminant overflowed")
+                .span_label(variant.span, &format!("overflowed on value after {}",
+                                                   prev_discr.unwrap()))
+                .note(&format!("explicitly set `{} = {}` if that is desired outcome",
+                               variant.node.name, wrapped_discr))
+                .emit();
+            None
+        }.unwrap_or(wrapped_discr));
+
         for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) {
             convert_field(ccx, f, ty_f)
         }
@@ -890,7 +918,7 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     did: DefId,
                                     name: ast::Name,
-                                    disr_val: ty::Disr,
+                                    discr: ty::VariantDiscr,
                                     def: &hir::VariantData)
                                     -> ty::VariantDef {
     let mut seen_fields: FxHashMap<ast::Name, Span> = FxHashMap();
@@ -918,7 +946,7 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     ty::VariantDef {
         did: did,
         name: name,
-        disr_val: disr_val,
+        discr: discr,
         fields: fields,
         ctor_kind: CtorKind::from_hir(def),
     }
@@ -932,8 +960,9 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let did = ccx.tcx.hir.local_def_id(it.id);
     // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
     let ctor_id = if !def.is_struct() { Some(ccx.tcx.hir.local_def_id(def.id())) } else { None };
-    let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name, 0, def)];
-    let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, None, variants,
+    let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
+                                               ty::VariantDiscr::Relative(0), def)];
+    let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants,
         ReprOptions::new(&ccx.tcx, did));
     if let Some(ctor_id) = ctor_id {
         // Make adt definition available through constructor id as well.
@@ -950,15 +979,16 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 -> &'tcx ty::AdtDef
 {
     let did = ccx.tcx.hir.local_def_id(it.id);
-    let variants = vec![convert_struct_variant(ccx, did, it.name, 0, def)];
-    let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, None, variants,
-                                    ReprOptions::new(&ccx.tcx, did));
+    let variants = vec![convert_struct_variant(ccx, did, it.name,
+                                               ty::VariantDiscr::Relative(0), def)];
+
+    let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did));
     ccx.tcx.adt_defs.borrow_mut().insert(did, adt);
     adt
 }
 
 fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId)
-                      -> Option<ConstInt> {
+                      -> Result<ConstInt, ()> {
     let e = &ccx.tcx.hir.body(body).value;
     debug!("disr expr, checking {}", ccx.tcx.hir.node_to_pretty_string(e.id));
 
@@ -987,17 +1017,16 @@ fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId
                 (attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) |
                 (attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) |
                 (attr::UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) |
-                (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) =>
-                    Some(i),
+                (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Ok(i),
                 (_, i) => {
                     print_err(ConstVal::Integral(i));
-                    None
+                    Err(())
                 },
             }
         },
         Ok(cv) => {
             print_err(cv);
-            None
+            Err(())
         },
         // enum variant evaluation happens before the global constant check
         // so we need to report the real error
@@ -1005,7 +1034,7 @@ fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId
             let mut diag = report_const_eval_err(
                 ccx.tcx, &err, e.span, "enum discriminant");
             diag.emit();
-            None
+            Err(())
         }
     }
 }
@@ -1016,36 +1045,22 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               -> &'tcx ty::AdtDef
 {
     let tcx = ccx.tcx;
-    let did = tcx.hir.local_def_id(it.id);
-    let repr_hints = tcx.lookup_repr_hints(did);
-    let repr_type = tcx.enum_repr_type(repr_hints.get(0));
-    let initial = ConstInt::new_inttype(repr_type.initial_discriminant(tcx), repr_type,
-                                        tcx.sess.target.uint_type, tcx.sess.target.int_type)
-        .unwrap();
-    let mut prev_disr = None::<ConstInt>;
+    let mut distance_from_explicit = 0;
     let variants = def.variants.iter().map(|v| {
-        let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr());
-        let disr = if let Some(e) = v.node.disr_expr {
-            // FIXME: i128 discriminants
-            evaluate_disr_expr(ccx, repr_type, e)
-        } else if let Some(disr) = prev_disr.map_or(Some(initial),
-                                                    |v| (v + ConstInt::Infer(1)).ok()) {
-            Some(disr)
-        } else {
-            struct_span_err!(tcx.sess, v.span, E0370,
-                             "enum discriminant overflowed")
-                .span_label(v.span, &format!("overflowed on value after {}", prev_disr.unwrap()))
-                .note(&format!("explicitly set `{} = {}` if that is desired outcome",
-                               v.node.name, wrapped_disr))
-                .emit();
-            None
-        }.unwrap_or(wrapped_disr);
-        prev_disr = Some(disr);
         let did = tcx.hir.local_def_id(v.node.data.id());
-        convert_struct_variant(ccx, did, v.node.name, disr.to_u128_unchecked(), &v.node.data)
+        let discr = if let Some(e) = v.node.disr_expr {
+            distance_from_explicit = 0;
+            ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.node_id))
+        } else {
+            ty::VariantDiscr::Relative(distance_from_explicit)
+        };
+        distance_from_explicit += 1;
+
+        convert_struct_variant(ccx, did, v.node.name, discr, &v.node.data)
     }).collect();
-    let adt = tcx.alloc_adt_def(did, AdtKind::Enum, Some(repr_type), variants,
-                                ReprOptions::new(&ccx.tcx, did));
+
+    let did = tcx.hir.local_def_id(it.id);
+    let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did));
     tcx.adt_defs.borrow_mut().insert(did, adt);
     adt
 }
index e12eff72c7f41f7e6de35ade2c315ed6c3321907..9911e093a898036d5fcae44fe656f6add46c2225 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 enum Enum {
-    P = 3, //~ NOTE first use of `3`
+    P = 3, //~ NOTE first use of `3isize`
     X = 3,
-    //~^ ERROR discriminant value `3` already exists
-    //~| NOTE enum already has `3`
+    //~^ ERROR discriminant value `3isize` already exists
+    //~| NOTE enum already has `3isize`
     Y = 5
 }
 
index 0d5f5fd75eba881378e45d963ba5f95e3521395a..658a0c1546b9f337b27704fa31d060075e91bdfc 100644 (file)
 
 enum Foo {
     A = 1,
-    //~^ NOTE first use of `1`
-    //~| NOTE first use of `1`
-    //~| NOTE first use of `1`
+    //~^ NOTE first use of `1isize`
+    //~| NOTE first use of `1isize`
+    //~| NOTE first use of `1isize`
     B = 1,
-    //~^ ERROR discriminant value `1` already exists
-    //~| NOTE enum already has `1`
+    //~^ ERROR discriminant value `1isize` already exists
+    //~| NOTE enum already has `1isize`
     C = 0,
     D,
-    //~^ ERROR discriminant value `1` already exists
-    //~| NOTE enum already has `1`
+    //~^ ERROR discriminant value `1isize` already exists
+    //~| NOTE enum already has `1isize`
 
     E = N,
-    //~^ ERROR discriminant value `1` already exists
-    //~| NOTE enum already has `1`
+    //~^ ERROR discriminant value `1isize` already exists
+    //~| NOTE enum already has `1isize`
 
 }