about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-01 16:01:24 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-12 12:33:16 +0100
commit740fb0cbaa0a5fd1770b256edf71d2c4587bff8f (patch)
treeda3eaf1f657cd0d88b5c7bbd408fa67ccdb59626
parent19ae2b940c03750adb3594ff4699c72af452c149 (diff)
downloadrust-740fb0cbaa0a5fd1770b256edf71d2c4587bff8f.tar.gz
rust-740fb0cbaa0a5fd1770b256edf71d2c4587bff8f.zip
Use IndexVec instead of `usize` in librustc
-rw-r--r--src/Cargo.lock1
-rw-r--r--src/librustc/middle/intrinsicck.rs14
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/mir/mod.rs11
-rw-r--r--src/librustc/mir/tcx.rs9
-rw-r--r--src/librustc/ty/context.rs4
-rw-r--r--src/librustc/ty/layout.rs71
-rw-r--r--src/librustc/ty/mod.rs30
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc_mir/const_eval.rs2
-rw-r--r--src/librustc_target/Cargo.toml1
-rw-r--r--src/librustc_target/abi/mod.rs22
-rw-r--r--src/librustc_target/lib.rs5
13 files changed, 108 insertions, 68 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 32304c81182..d80aa902c8b 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -2400,6 +2400,7 @@ dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
+ "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
 ]
 
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 0a5b1e184de..d2be0e4dcb9 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -11,9 +11,10 @@
 use hir::def::Def;
 use hir::def_id::DefId;
 use ty::{self, Ty, TyCtxt};
-use ty::layout::{LayoutError, Pointer, SizeSkeleton};
+use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 
 use rustc_target::spec::abi::Abi::RustIntrinsic;
+use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir;
@@ -48,10 +49,13 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() {
         let data_idx;
 
-        if def.variants[0].fields.is_empty() {
-            data_idx = 1;
-        } else if def.variants[1].fields.is_empty() {
-            data_idx = 0;
+        let one = VariantIdx::new(1);
+        let zero = VariantIdx::new(0);
+
+        if def.variants[zero].fields.is_empty() {
+            data_idx = one;
+        } else if def.variants[one].fields.is_empty() {
+            data_idx = zero;
         } else {
             return ty;
         }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 9d3f37bc36a..59ef8fa1448 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -76,6 +76,7 @@ use hir::def::{Def, CtorKind};
 use ty::adjustment;
 use ty::{self, Ty, TyCtxt};
 use ty::fold::TypeFoldable;
+use ty::layout::VariantIdx;
 
 use hir::{MutImmutable, MutMutable, PatKind};
 use hir::pat_util::EnumerateAndAdjustIterator;
@@ -87,6 +88,7 @@ use std::borrow::Cow;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
 use std::rc::Rc;
 use util::nodemap::ItemLocalSet;
 
@@ -227,7 +229,7 @@ impl<'tcx> cmt_<'tcx> {
             }
             _ => {
                 assert_eq!(adt_def.variants.len(), 1);
-                &adt_def.variants[0]
+                &adt_def.variants[VariantIdx::new(0)]
             }
         };
         Some((adt_def, &variant_def.fields[field_index]))
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index b8ccec4fec7..8a0306ab346 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -40,6 +40,7 @@ use syntax_pos::{Span, DUMMY_SP};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::subst::{CanonicalUserSubsts, Subst, Substs};
 use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
+use ty::layout::VariantIdx;
 use util::ppaux;
 
 pub use mir::interpret::AssertMessage;
@@ -1939,7 +1940,7 @@ pub enum ProjectionElem<'tcx, V, T> {
     /// "Downcast" to a variant of an ADT. Currently, we only introduce
     /// this for ADTs with more than one variant. It may be better to
     /// just introduce it always, or always for enums.
-    Downcast(&'tcx AdtDef, u32),
+    Downcast(&'tcx AdtDef, VariantIdx),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
@@ -1974,8 +1975,8 @@ impl<'tcx> Place<'tcx> {
         self.elem(ProjectionElem::Deref)
     }
 
-    pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> {
-        self.elem(ProjectionElem::Downcast(adt_def, variant_index as u32))
+    pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
+        self.elem(ProjectionElem::Downcast(adt_def, variant_index))
     }
 
     pub fn index(self, index: Local) -> Place<'tcx> {
@@ -2026,7 +2027,7 @@ impl<'tcx> Debug for Place<'tcx> {
             Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1),
             Projection(ref data) => match data.elem {
                 ProjectionElem::Downcast(ref adt_def, index) => {
-                    write!(fmt, "({:?} as {})", data.base, adt_def.variants[index as usize].name)
+                    write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name)
                 }
                 ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
                 ProjectionElem::Field(field, ty) => {
@@ -2216,7 +2217,7 @@ pub enum AggregateKind<'tcx> {
     /// active field index would identity the field `c`
     Adt(
         &'tcx AdtDef,
-        usize,
+        VariantIdx,
         &'tcx Substs<'tcx>,
         Option<UserTypeAnnotation<'tcx>>,
         Option<usize>,
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index c9a396ff8c5..baa88dba459 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -16,6 +16,7 @@
 use mir::*;
 use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, Ty, TyCtxt};
+use ty::layout::VariantIdx;
 use hir;
 use ty::util::IntTypeExt;
 
@@ -27,7 +28,7 @@ pub enum PlaceTy<'tcx> {
     /// Downcast to a particular variant of an enum.
     Downcast { adt_def: &'tcx AdtDef,
                substs: &'tcx Substs<'tcx>,
-               variant_index: u32 },
+               variant_index: VariantIdx },
 }
 
 static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
@@ -58,11 +59,11 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
     {
         // Pass `0` here so it can be used as a "default" variant_index in first arm below
-        let answer = match (self, 0) {
+        let answer = match (self, VariantIdx::new(0)) {
             (PlaceTy::Ty {
                 ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
             (PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
-                let variant_def = &adt_def.variants[variant_index as usize];
+                let variant_def = &adt_def.variants[variant_index];
                 let field_def = &variant_def.fields[f.index()];
                 field_def.ty(tcx, substs)
             }
@@ -138,7 +139,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
                 match self.to_ty(tcx).sty {
                     ty::Adt(adt_def, substs) => {
                         assert!(adt_def.is_enum());
-                        assert!(index < adt_def.variants.len() as u32);
+                        assert!(index.as_usize() < adt_def.variants.len());
                         assert_eq!(adt_def, adt_def1);
                         PlaceTy::Downcast { adt_def,
                                             substs,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 82095a2f5b0..a86a56a45cd 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -45,7 +45,7 @@ use ty::RegionKind;
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
 use ty::TyKind::*;
 use ty::GenericParamDefKind;
-use ty::layout::{LayoutDetails, TargetDataLayout};
+use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
 use ty::query;
 use ty::steal::Steal;
 use ty::BindingMode;
@@ -1009,7 +1009,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn alloc_adt_def(self,
                          did: DefId,
                          kind: AdtKind,
-                         variants: Vec<ty::VariantDef>,
+                         variants: IndexVec<VariantIdx, ty::VariantDef>,
                          repr: ReprOptions)
                          -> &'gcx ty::AdtDef {
         let def = ty::AdtDef::new(self, did, kind, variants, repr);
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 5aeba652f32..877bd5a82e6 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -23,6 +23,7 @@ use std::mem;
 use std::ops::Bound;
 
 use ich::StableHashingContext;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 
@@ -229,7 +230,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             let b_offset = a.value.size(dl).abi_align(b.value.align(dl));
             let size = (b_offset + b.value.size(dl)).abi_align(align);
             LayoutDetails {
-                variants: Variants::Single { index: 0 },
+                variants: Variants::Single { index: VariantIdx::new(0) },
                 fields: FieldPlacement::Arbitrary {
                     offsets: vec![Size::ZERO, b_offset],
                     memory_index: vec![0, 1]
@@ -454,7 +455,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             }
 
             Ok(LayoutDetails {
-                variants: Variants::Single { index: 0 },
+                variants: Variants::Single { index: VariantIdx::new(0) },
                 fields: FieldPlacement::Arbitrary {
                     offsets,
                     memory_index
@@ -499,7 +500,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             // The never type.
             ty::Never => {
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Union(0),
                     abi: Abi::Uninhabited,
                     align: dl.i8_align,
@@ -555,7 +556,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     .ok_or(LayoutError::SizeOverflow(ty))?;
 
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: element.size,
                         count
@@ -568,7 +569,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             ty::Slice(element) => {
                 let element = self.layout_of(element)?;
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: element.size,
                         count: 0
@@ -580,7 +581,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             }
             ty::Str => {
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: Size::from_bytes(1),
                         count: 0
@@ -650,7 +651,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 let size = size.abi_align(align);
 
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: element.size,
                         count
@@ -671,7 +672,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     v.fields.iter().map(|field| {
                         self.layout_of(field.ty(tcx, substs))
                     }).collect::<Result<Vec<_>, _>>()
-                }).collect::<Result<Vec<_>, _>>()?;
+                }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
                 if def.is_union() {
                     let packed = def.repr.packed();
@@ -697,7 +698,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     }
 
                     let mut size = Size::ZERO;
-                    for field in &variants[0] {
+                    let index = VariantIdx::new(0);
+                    for field in &variants[index] {
                         assert!(!field.is_unsized());
 
                         if packed {
@@ -710,8 +712,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     }
 
                     return Ok(tcx.intern_layout(LayoutDetails {
-                        variants: Variants::Single { index: 0 },
-                        fields: FieldPlacement::Union(variants[0].len()),
+                        variants: Variants::Single { index },
+                        fields: FieldPlacement::Union(variants[index].len()),
                         abi: Abi::Aggregate { sized: true },
                         align,
                         size: size.abi_align(align)
@@ -729,8 +731,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     uninhabited && is_zst
                 };
                 let (present_first, present_second) = {
-                    let mut present_variants = (0..variants.len()).filter(|&v| {
-                        !absent(&variants[v])
+                    let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| {
+                        if absent(v) {
+                            None
+                        } else {
+                            Some(i)
+                        }
                     });
                     (present_variants.next(), present_variants.next())
                 };
@@ -792,16 +798,16 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 // The current code for niche-filling relies on variant indices
                 // instead of actual discriminants, so dataful enums with
                 // explicit discriminants (RFC #2363) would misbehave.
-                let no_explicit_discriminants = def.variants.iter().enumerate()
-                    .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
+                let no_explicit_discriminants = def.variants.iter_enumerated()
+                    .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32()));
 
                 // Niche-filling enum optimization.
                 if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
                     let mut dataful_variant = None;
-                    let mut niche_variants = usize::max_value()..=0;
+                    let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
 
                     // Find one non-ZST variant.
-                    'variants: for (v, fields) in variants.iter().enumerate() {
+                    'variants: for (v, fields) in variants.iter_enumerated() {
                         if absent(fields) {
                             continue 'variants;
                         }
@@ -824,7 +830,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     }
 
                     if let Some(i) = dataful_variant {
-                        let count = (niche_variants.end() - niche_variants.start() + 1) as u128;
+                        let count = (
+                            niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1
+                        ) as u128;
                         for (field_index, &field) in variants[i].iter().enumerate() {
                             let niche = match self.find_niche(field)? {
                                 Some(niche) => niche,
@@ -836,7 +844,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                             };
 
                             let mut align = dl.aggregate_align;
-                            let st = variants.iter().enumerate().map(|(j, v)| {
+                            let st = variants.iter_enumerated().map(|(j, v)| {
                                 let mut st = univariant_uninterned(v,
                                     &def.repr, StructKind::AlwaysSized)?;
                                 st.variants = Variants::Single { index: j };
@@ -844,7 +852,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                                 align = align.max(st.align);
 
                                 Ok(st)
-                            }).collect::<Result<Vec<_>, _>>()?;
+                            }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
                             let offset = st[i].fields.offset(field_index) + niche.offset;
                             let size = st[i].size;
@@ -899,7 +907,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 let (mut min, mut max) = (i128::max_value(), i128::min_value());
                 let discr_type = def.repr.discr_type();
                 let bits = Integer::from_attr(self, discr_type).size().bits();
-                for (i, discr) in def.discriminants(tcx).enumerate() {
+                for (i, discr) in def.discriminants(tcx) {
                     if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
                         continue;
                     }
@@ -941,7 +949,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
 
                 // Create the set of structs that represent each variant.
-                let mut layout_variants = variants.iter().enumerate().map(|(i, field_layouts)| {
+                let mut layout_variants = variants.iter_enumerated().map(|(i, field_layouts)| {
                     let mut st = univariant_uninterned(&field_layouts,
                         &def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?;
                     st.variants = Variants::Single { index: i };
@@ -956,7 +964,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     size = cmp::max(size, st.size);
                     align = align.max(st.align);
                     Ok(st)
-                }).collect::<Result<Vec<_>, _>>()?;
+                }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
                 // Align the maximum variant size to the largest alignment.
                 size = size.abi_align(align);
@@ -1259,7 +1267,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 debug!("print-type-size `{:#?}` adt general variants def {}",
                        layout.ty, adt_def.variants.len());
                 let variant_infos: Vec<_> =
-                    adt_def.variants.iter().enumerate().map(|(i, variant_def)| {
+                    adt_def.variants.iter_enumerated().map(|(i, variant_def)| {
                         let fields: Vec<_> =
                             variant_def.fields.iter().map(|f| f.ident.name).collect();
                         build_variant_info(Some(variant_def.name),
@@ -1339,7 +1347,8 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
                 }
 
                 // Get a zero-sized variant or a pointer newtype.
-                let zero_or_ptr_variant = |i: usize| {
+                let zero_or_ptr_variant = |i| {
+                    let i = VariantIdx::new(i);
                     let fields = def.variants[i].fields.iter().map(|field| {
                         SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
                     });
@@ -1562,7 +1571,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
     where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
           C::TyLayout: MaybeResult<TyLayout<'tcx>>
 {
-    fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: usize) -> TyLayout<'tcx> {
+    fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
         let details = match this.variants {
             Variants::Single { index } if index == variant_index => this.details,
 
@@ -1882,6 +1891,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for FieldPlacement {
     }
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for VariantIdx {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        self.as_u32().hash_stable(hcx, hasher)
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for Abi {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 0ba28811a90..6d59457cc74 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -32,6 +32,7 @@ use mir::GeneratorLayout;
 use session::CrateDisambiguator;
 use traits::{self, Reveal};
 use ty;
+use ty::layout::VariantIdx;
 use ty::subst::{Subst, Substs};
 use ty::util::{IntTypeExt, Discr};
 use ty::walk::TypeWalker;
@@ -57,7 +58,7 @@ use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
 use smallvec;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
 
@@ -1785,7 +1786,7 @@ pub enum VariantDiscr {
     /// 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),
+    Relative(u32),
 }
 
 #[derive(Debug)]
@@ -1801,8 +1802,7 @@ pub struct FieldDef {
 /// table.
 pub struct AdtDef {
     pub did: DefId,
-    // TODO: make this an IndexVec
-    pub variants: Vec<VariantDef>,
+    pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
     flags: AdtFlags,
     pub repr: ReprOptions,
 }
@@ -2000,7 +2000,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     fn new(tcx: TyCtxt<'_, '_, '_>,
            did: DefId,
            kind: AdtKind,
-           variants: Vec<VariantDef>,
+           variants: IndexVec<VariantIdx, VariantDef>,
            repr: ReprOptions) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
@@ -2122,7 +2122,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(&self) -> &VariantDef {
         assert!(self.is_struct() || self.is_union());
-        &self.variants[0]
+        &self.variants[VariantIdx::new(0)]
     }
 
     #[inline]
@@ -2217,11 +2217,11 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     pub fn discriminants(
         &'a self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
+    ) -> impl Iterator<Item=(VariantIdx, Discr<'tcx>)> + Captures<'gcx> + 'a {
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx.global_tcx());
         let mut prev_discr = None::<Discr<'tcx>>;
-        self.variants.iter().map(move |v| {
+        self.variants.iter_enumerated().map(move |(i, v)| {
             let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
             if let VariantDiscr::Explicit(expr_did) = v.discr {
                 if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
@@ -2230,7 +2230,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
             }
             prev_discr = Some(discr);
 
-            discr
+            (i, discr)
         })
     }
 
@@ -2241,7 +2241,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     /// assuming there are no constant-evaluation errors there.
     pub fn discriminant_for_variant(&self,
                                     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                    variant_index: usize)
+                                    variant_index: VariantIdx)
                                     -> Discr<'tcx> {
         let (val, offset) = self.discriminant_def_for_variant(variant_index);
         let explicit_value = val
@@ -2255,12 +2255,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     /// inferred discriminant directly
     pub fn discriminant_def_for_variant(
         &self,
-        variant_index: usize,
-    ) -> (Option<DefId>, usize) {
-        let mut explicit_index = variant_index;
+        variant_index: VariantIdx,
+    ) -> (Option<DefId>, u32) {
+        let mut explicit_index = variant_index.as_u32();
         let expr_did;
         loop {
-            match self.variants[explicit_index].discr {
+            match self.variants[VariantIdx::from_u32(explicit_index)].discr {
                 ty::VariantDiscr::Relative(0) => {
                     expr_did = None;
                     break;
@@ -2274,7 +2274,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 }
             }
         }
-        (expr_did, variant_index - explicit_index)
+        (expr_did, variant_index.as_u32() - explicit_index)
     }
 
     pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 17a5f0999e7..e92f92dce63 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -33,7 +33,7 @@ CloneTypeFoldableAndLiftImpls! {
     (),
     bool,
     usize,
-    u32,
+    ::ty::layout::VariantIdx,
     u64,
     ::middle::region::Scope,
     ::syntax::ast::FloatTy,
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 011887090ee..8020893634c 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -481,7 +481,7 @@ pub fn const_field<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     instance: ty::Instance<'tcx>,
-    variant: Option<usize>,
+    variant: Option<u32>,
     field: mir::Field,
     value: &'tcx ty::Const<'tcx>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml
index 684ea4c7897..dfdd7f0ae58 100644
--- a/src/librustc_target/Cargo.toml
+++ b/src/librustc_target/Cargo.toml
@@ -12,4 +12,5 @@ crate-type = ["dylib"]
 bitflags = "1.0"
 log = "0.4"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
+rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 15f61a03344..01811aced73 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -16,6 +16,8 @@ use spec::Target;
 use std::{cmp, fmt};
 use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+
 pub mod call;
 
 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
@@ -825,11 +827,15 @@ impl Abi {
     }
 }
 
+newtype_index! {
+    pub struct VariantIdx { .. }
+}
+
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub enum Variants {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single {
-        index: usize
+        index: VariantIdx,
     },
 
     /// General-case enums: for each case there is a struct, and they all have
@@ -837,7 +843,7 @@ pub enum Variants {
     /// at a non-0 offset, after where the tag would go.
     Tagged {
         tag: Scalar,
-        variants: Vec<LayoutDetails>,
+        variants: IndexVec<VariantIdx, LayoutDetails>,
     },
 
     /// Multiple cases distinguished by a niche (values invalid for a type):
@@ -849,11 +855,11 @@ pub enum Variants {
     /// `None` has a null pointer for the second tuple field, and
     /// `Some` is the identity function (with a non-null reference).
     NicheFilling {
-        dataful_variant: usize,
-        niche_variants: RangeInclusive<usize>,
+        dataful_variant: VariantIdx,
+        niche_variants: RangeInclusive<VariantIdx>,
         niche: Scalar,
         niche_start: u128,
-        variants: Vec<LayoutDetails>,
+        variants: IndexVec<VariantIdx, LayoutDetails>,
     }
 }
 
@@ -871,7 +877,7 @@ impl LayoutDetails {
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
         LayoutDetails {
-            variants: Variants::Single { index: 0 },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldPlacement::Union(0),
             abi: Abi::Scalar(scalar),
             size,
@@ -908,12 +914,12 @@ pub trait LayoutOf {
 }
 
 pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
-    fn for_variant(this: TyLayout<'a, Self>, cx: &C, variant_index: usize) -> TyLayout<'a, Self>;
+    fn for_variant(this: TyLayout<'a, Self>, cx: &C, variant_index: VariantIdx) -> TyLayout<'a, Self>;
     fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout;
 }
 
 impl<'a, Ty> TyLayout<'a, Ty> {
-    pub fn for_variant<C>(self, cx: &C, variant_index: usize) -> Self
+    pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
     where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
         Ty::for_variant(self, cx, variant_index)
     }
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index e60c9922d46..813b39de064 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -23,7 +23,9 @@
 
 #![feature(box_syntax)]
 #![feature(nll)]
+#![feature(rustc_attrs)]
 #![feature(slice_patterns)]
+#![feature(step_trait)]
 
 #[macro_use]
 extern crate bitflags;
@@ -36,5 +38,8 @@ extern crate serialize as rustc_serialize; // used by deriving
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
 
+#[macro_use]
+extern crate rustc_data_structures;
+
 pub mod abi;
 pub mod spec;