diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 4df0fc443a27c..f5a46060759dd 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -39,10 +39,12 @@ pub struct DepGraph {
     fingerprints: Lrc<Lock<IndexVec<DepNodeIndex, Fingerprint>>>
 }
 
-newtype_index!(DepNodeIndex);
+newtype_index! {
+    pub struct DepNodeIndex { .. }
+}
 
 impl DepNodeIndex {
-    const INVALID: DepNodeIndex = DepNodeIndex(::std::u32::MAX);
+    const INVALID: DepNodeIndex = DepNodeIndex::MAX;
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -1125,14 +1127,16 @@ impl DepNodeColorMap {
         match self.values[index] {
             COMPRESSED_NONE => None,
             COMPRESSED_RED => Some(DepNodeColor::Red),
-            value => Some(DepNodeColor::Green(DepNodeIndex(value - COMPRESSED_FIRST_GREEN)))
+            value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(
+                value - COMPRESSED_FIRST_GREEN
+            )))
         }
     }
 
     fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
         self.values[index] = match color {
             DepNodeColor::Red => COMPRESSED_RED,
-            DepNodeColor::Green(index) => index.0 + COMPRESSED_FIRST_GREEN,
+            DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN,
         }
     }
 }
diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs
index 60fc813a25d51..4c896a33e59c1 100644
--- a/src/librustc/dep_graph/serialized.rs
+++ b/src/librustc/dep_graph/serialized.rs
@@ -14,7 +14,9 @@ use dep_graph::DepNode;
 use ich::Fingerprint;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
-newtype_index!(SerializedDepNodeIndex);
+newtype_index! {
+    pub struct SerializedDepNodeIndex { .. }
+}
 
 /// Data for use when recompiling the **current crate**.
 #[derive(Debug, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index be37ea18457f1..420ffbcfee6cd 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -15,8 +15,8 @@ use serialize;
 use std::fmt;
 use std::u32;
 
-newtype_index!(CrateNum
-    {
+newtype_index! {
+    pub struct CrateNum {
         ENCODABLE = custom
         DEBUG_FORMAT = "crate{}",
 
@@ -27,32 +27,20 @@ newtype_index!(CrateNum
         /// Virtual crate for builtin macros
         // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
         // `CrateNum`s.
-        const BUILTIN_MACROS_CRATE = u32::MAX,
+        const BUILTIN_MACROS_CRATE = CrateNum::MAX_AS_U32,
 
         /// A CrateNum value that indicates that something is wrong.
-        const INVALID_CRATE = u32::MAX - 1,
+        const INVALID_CRATE = CrateNum::MAX_AS_U32 - 1,
 
         /// A special CrateNum that we use for the tcx.rcache when decoding from
         /// the incr. comp. cache.
-        const RESERVED_FOR_INCR_COMP_CACHE = u32::MAX - 2,
-    });
+        const RESERVED_FOR_INCR_COMP_CACHE = CrateNum::MAX_AS_U32 - 2,
+    }
+}
 
 impl CrateNum {
     pub fn new(x: usize) -> CrateNum {
-        assert!(x < (u32::MAX as usize));
-        CrateNum(x as u32)
-    }
-
-    pub fn from_u32(x: u32) -> CrateNum {
-        CrateNum(x)
-    }
-
-    pub fn as_usize(&self) -> usize {
-        self.0 as usize
-    }
-
-    pub fn as_u32(&self) -> u32 {
-        self.0
+        CrateNum::from_usize(x)
     }
 
     pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } }
@@ -60,7 +48,7 @@ impl CrateNum {
 
 impl fmt::Display for CrateNum {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
+        fmt::Display::fmt(&self.as_u32(), f)
     }
 }
 
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index f11e448796462..8b7438cbe6325 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -102,7 +102,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::Local {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
@@ -112,7 +111,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::BasicBlock {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
@@ -122,7 +120,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::Field {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
@@ -133,7 +130,6 @@ for mir::SourceScope {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
@@ -143,7 +139,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::Promoted {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 68320dfddefbc..e90c4f62f59d5 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -143,7 +143,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
@@ -153,7 +152,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CanonicalVar {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
@@ -774,7 +772,6 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
     FnPtrAddrCast
 });
 
-impl_stable_hash_for!(tuple_struct ::middle::region::FirstStatementIndex { idx });
 impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index ac6a7f0c2baa8..eabcf1ce41363 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -73,8 +73,6 @@ use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 
-use rustc_data_structures::indexed_vec::Idx;
-
 mod note;
 
 mod need_type_info;
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 296808cea2bd7..d8f3b9a05bd40 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -16,7 +16,7 @@ use self::CombineMapType::*;
 use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
 use super::unify_key;
 
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::unify as ut;
 use ty::{self, Ty, TyCtxt};
diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs
index a1145572b79d9..cdc92877a5ae8 100644
--- a/src/librustc/infer/unify_key.rs
+++ b/src/librustc/infer/unify_key.rs
@@ -49,8 +49,8 @@ impl UnifyValue for RegionVidKey {
 
 impl UnifyKey for ty::RegionVid {
     type Value = RegionVidKey;
-    fn index(&self) -> u32 { self.0 }
-    fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid(i) }
+    fn index(&self) -> u32 { u32::from(*self) }
+    fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid::from(i) }
     fn tag() -> &'static str { "RegionVid" }
 }
 
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index e281cbf948893..f6a8f8dc172d4 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -159,11 +159,13 @@ pub struct BlockRemainder {
     pub first_statement_index: FirstStatementIndex,
 }
 
-newtype_index!(FirstStatementIndex
-    {
-        pub idx
+newtype_index! {
+    pub struct FirstStatementIndex {
         MAX = SCOPE_DATA_REMAINDER_MAX
-    });
+    }
+}
+
+impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private });
 
 impl From<ScopeData> for Scope {
     #[inline]
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index f66be6dc54d37..c6a1281061fe4 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -131,9 +131,6 @@ pub struct Mir<'tcx> {
     cache: cache::Cache,
 }
 
-/// where execution begins
-pub const START_BLOCK: BasicBlock = BasicBlock(0);
-
 impl<'tcx> Mir<'tcx> {
     pub fn new(
         basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
@@ -239,7 +236,7 @@ impl<'tcx> Mir<'tcx> {
 
     #[inline]
     pub fn local_kind(&self, local: Local) -> LocalKind {
-        let index = local.0 as usize;
+        let index = local.as_usize();
         if index == 0 {
             debug_assert!(
                 self.local_decls[local].mutability == Mutability::Mut,
@@ -523,11 +520,12 @@ impl BorrowKind {
 ///////////////////////////////////////////////////////////////////////////
 // Variables and temps
 
-newtype_index!(Local
-    {
+newtype_index! {
+    pub struct Local {
         DEBUG_FORMAT = "_{}",
         const RETURN_PLACE = 0,
-    });
+    }
+}
 
 /// Classifies locals into categories. See `Mir::local_kind`.
 #[derive(PartialEq, Eq, Debug)]
@@ -852,7 +850,12 @@ pub struct UpvarDecl {
 ///////////////////////////////////////////////////////////////////////////
 // BasicBlock
 
-newtype_index!(BasicBlock { DEBUG_FORMAT = "bb{}" });
+newtype_index! {
+    pub struct BasicBlock {
+        DEBUG_FORMAT = "bb{}",
+        const START_BLOCK = 0,
+    }
+}
 
 impl BasicBlock {
     pub fn start_location(self) -> Location {
@@ -1822,7 +1825,11 @@ pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
 
-newtype_index!(Field { DEBUG_FORMAT = "field[{}]" });
+newtype_index! {
+    pub struct Field {
+        DEBUG_FORMAT = "field[{}]"
+    }
+}
 
 impl<'tcx> Place<'tcx> {
     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -1895,11 +1902,12 @@ impl<'tcx> Debug for Place<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // Scopes
 
-newtype_index!(SourceScope
-    {
+newtype_index! {
+    pub struct SourceScope {
         DEBUG_FORMAT = "scope[{}]",
         const OUTERMOST_SOURCE_SCOPE = 0,
-    });
+    }
+}
 
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct SourceScopeData {
@@ -2271,7 +2279,11 @@ pub struct Constant<'tcx> {
     pub literal: &'tcx ty::Const<'tcx>,
 }
 
-newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });
+newtype_index! {
+    pub struct Promoted {
+        DEBUG_FORMAT = "promoted[{}]"
+    }
+}
 
 impl<'tcx> Debug for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 7c7ee9b330ecc..b5ec1ad36ab7e 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1034,11 +1034,12 @@ impl<'a, 'gcx, 'tcx> ParamTy {
 /// is the outer fn.
 ///
 /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
-newtype_index!(DebruijnIndex
-    {
+newtype_index! {
+    pub struct DebruijnIndex {
         DEBUG_FORMAT = "DebruijnIndex({})",
         const INNERMOST = 0,
-    });
+    }
+}
 
 pub type Region<'tcx> = &'tcx RegionKind;
 
@@ -1176,11 +1177,11 @@ pub struct FloatVid {
     pub index: u32,
 }
 
-newtype_index!(RegionVid
-    {
-        pub idx
+newtype_index! {
+    pub struct RegionVid {
         DEBUG_FORMAT = custom,
-    });
+    }
+}
 
 impl Atom for RegionVid {
     fn index(self) -> usize {
@@ -1188,18 +1189,6 @@ impl Atom for RegionVid {
     }
 }
 
-impl From<usize> for RegionVid {
-    fn from(i: usize) -> RegionVid {
-        RegionVid::new(i)
-    }
-}
-
-impl From<RegionVid> for usize {
-    fn from(vid: RegionVid) -> usize {
-        Idx::index(vid)
-    }
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub enum InferTy {
     TyVar(TyVid),
@@ -1217,7 +1206,9 @@ pub enum InferTy {
     CanonicalTy(CanonicalVar),
 }
 
-newtype_index!(CanonicalVar);
+newtype_index! {
+    pub struct CanonicalVar { .. }
+}
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -1282,8 +1273,8 @@ impl DebruijnIndex {
     ///
     /// you would need to shift the index for `'a` into 1 new binder.
     #[must_use]
-    pub const fn shifted_in(self, amount: u32) -> DebruijnIndex {
-        DebruijnIndex(self.0 + amount)
+    pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
+        DebruijnIndex::from_u32(self.as_u32() + amount)
     }
 
     /// Update this index in place by shifting it "in" through
@@ -1295,8 +1286,8 @@ impl DebruijnIndex {
     /// Returns the resulting index when this value is moved out from
     /// `amount` number of new binders.
     #[must_use]
-    pub const fn shifted_out(self, amount: u32) -> DebruijnIndex {
-        DebruijnIndex(self.0 - amount)
+    pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
+        DebruijnIndex::from_u32(self.as_u32() - amount)
     }
 
     /// Update in place by shifting out from `amount` binders.
@@ -1325,11 +1316,11 @@ impl DebruijnIndex {
     /// bound by one of the binders we are shifting out of, that is an
     /// error (and should fail an assertion failure).
     pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
-        self.shifted_out((to_binder.0 - INNERMOST.0) as u32)
+        self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
     }
 }
 
-impl_stable_hash_for!(tuple_struct DebruijnIndex { index });
+impl_stable_hash_for!(struct DebruijnIndex { private });
 
 /// Region utilities
 impl RegionKind {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 0f15c75c2fb36..e8236e21e2463 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -26,7 +26,6 @@ use std::cell::Cell;
 use std::fmt;
 use std::usize;
 
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::CRATE_NODE_ID;
 use syntax::symbol::{Symbol, InternedString};
diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs
index 9e65144bd60a1..258fe643c3067 100644
--- a/src/librustc_codegen_llvm/mir/mod.rs
+++ b/src/librustc_codegen_llvm/mir/mod.rs
@@ -32,7 +32,7 @@ use syntax::symbol::keywords;
 use std::iter;
 
 use rustc_data_structures::bitvec::BitArray;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::IndexVec;
 
 pub use self::constant::codegen_static_initializer;
 
diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs
index 419e7298588c5..bfa0e0a451e6f 100644
--- a/src/librustc_codegen_llvm/mir/operand.rs
+++ b/src/librustc_codegen_llvm/mir/operand.rs
@@ -13,7 +13,6 @@ use rustc::mir;
 use rustc::mir::interpret::{ConstValue, ScalarMaybeUndef};
 use rustc::ty;
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
 
 use base;
diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs
index 833dca8c75fd5..4baab1763c310 100644
--- a/src/librustc_codegen_llvm/mir/place.rs
+++ b/src/librustc_codegen_llvm/mir/place.rs
@@ -13,7 +13,6 @@ use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
 use rustc::mir;
 use rustc::mir::tcx::PlaceTy;
-use rustc_data_structures::indexed_vec::Idx;
 use base;
 use builder::Builder;
 use common::{CodegenCx, C_undef, C_usize, C_u8, C_u32, C_uint, C_null, C_uint_big};
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index c358f2f852e18..186bc6d43ccc5 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -48,25 +48,42 @@ impl Idx for u32 {
     fn index(self) -> usize { self as usize }
 }
 
+/// Creates a struct type `S` that can be used as an index with
+/// `IndexVec` and so on.
+///
+/// There are two ways of interacting with these indices:
+///
+/// - The `From` impls are the preferred way. So you can do
+///   `S::from(v)` with a `usize` or `u32`. And you can convert back
+///   to an integer with `u32::from(s)`.
+///
+/// - Alternatively, you can use the methods `S::new(v)` and `s.index()`
+///   to create/return a value.
+///
+/// Internally, the index uses a u32, so the index must not exceed
+/// `u32::MAX`. You can also customize things like the `Debug` impl,
+/// what traits are derived, and so forth via the macro.
 #[macro_export]
 macro_rules! newtype_index {
     // ---- public rules ----
 
     // Use default constants
-    ($name:ident) => (
+    ($v:vis struct $name:ident { .. }) => (
         newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
             @type         [$name]
-            @max          [::std::u32::MAX]
+            @max          [::std::u32::MAX - 1]
+            @vis          [$v]
             @debug_format ["{}"]);
     );
 
     // Define any constants
-    ($name:ident { $($tokens:tt)+ }) => (
+    ($v:vis struct $name:ident { $($tokens:tt)+ }) => (
         newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
             @type         [$name]
-            @max          [::std::u32::MAX]
+            @max          [::std::u32::MAX - 1]
+            @vis          [$v]
             @debug_format ["{}"]
                           $($tokens)+);
     );
@@ -75,27 +92,92 @@ macro_rules! newtype_index {
 
     // Base case, user-defined constants (if any) have already been defined
     (@derives      [$($derives:ident,)*]
-     @pub          [$($pub:tt)*]
      @type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]) => (
         #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
-        pub struct $type($($pub)* u32);
+        $v struct $type {
+            private: u32
+        }
+
+        impl $type {
+            $v const MAX_AS_U32: u32 = $max;
+
+            $v const MAX: $type = $type::from_u32_const($max);
+
+            #[inline]
+            $v fn from_usize(value: usize) -> Self {
+                assert!(value <= ($max as usize));
+                unsafe {
+                    $type::from_u32_unchecked(value as u32)
+                }
+            }
+
+            #[inline]
+            $v fn from_u32(value: u32) -> Self {
+                assert!(value <= $max);
+                unsafe {
+                    $type::from_u32_unchecked(value)
+                }
+            }
+
+            /// Hacky variant of `from_u32` for use in constants.
+            /// This version checks the "max" constraint by using an
+            /// invalid array dereference.
+            #[inline]
+            $v const fn from_u32_const(value: u32) -> Self {
+                // This will fail at const eval time unless `value <=
+                // max` is true (in which case we get the index 0).
+                // It will also fail at runtime, of course, but in a
+                // kind of wacky way.
+                let _ = ["out of range value used"][
+                    !(value <= $max) as usize
+                ];
+
+                unsafe {
+                    $type { private: value }
+                }
+            }
+
+            #[inline]
+            $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
+                $type { private: value }
+            }
+
+            /// Extract value of this index as an integer.
+            #[inline]
+            $v fn index(self) -> usize {
+                self.as_usize()
+            }
+
+            /// Extract value of this index as a usize.
+            #[inline]
+            $v fn as_u32(self) -> u32 {
+                self.private
+            }
+
+            /// Extract value of this index as a u32.
+            #[inline]
+            $v fn as_usize(self) -> usize {
+                self.as_u32() as usize
+            }
+        }
 
         impl Idx for $type {
             #[inline]
             fn new(value: usize) -> Self {
-                assert!(value < ($max) as usize);
-                $type(value as u32)
+                Self::from(value)
             }
 
             #[inline]
             fn index(self) -> usize {
-                self.0 as usize
+                usize::from(self)
             }
         }
 
         impl ::std::iter::Step for $type {
+            #[inline]
             fn steps_between(start: &Self, end: &Self) -> Option<usize> {
                 <usize as ::std::iter::Step>::steps_between(
                     &Idx::index(*start),
@@ -103,27 +185,60 @@ macro_rules! newtype_index {
                 )
             }
 
+            #[inline]
             fn replace_one(&mut self) -> Self {
                 ::std::mem::replace(self, Self::new(1))
             }
 
+            #[inline]
             fn replace_zero(&mut self) -> Self {
                 ::std::mem::replace(self, Self::new(0))
             }
 
+            #[inline]
             fn add_one(&self) -> Self {
                 Self::new(Idx::index(*self) + 1)
             }
 
+            #[inline]
             fn sub_one(&self) -> Self {
                 Self::new(Idx::index(*self) - 1)
             }
 
+            #[inline]
             fn add_usize(&self, u: usize) -> Option<Self> {
                 Idx::index(*self).checked_add(u).map(Self::new)
             }
         }
 
+        impl From<$type> for u32 {
+            #[inline]
+            fn from(v: $type) -> u32 {
+                v.as_u32()
+            }
+        }
+
+        impl From<$type> for usize {
+            #[inline]
+            fn from(v: $type) -> usize {
+                v.as_usize()
+            }
+        }
+
+        impl From<usize> for $type {
+            #[inline]
+            fn from(value: usize) -> Self {
+                $type::from_usize(value)
+            }
+        }
+
+        impl From<u32> for $type {
+            #[inline]
+            fn from(value: u32) -> Self {
+                $type::from_u32(value)
+            }
+        }
+
         newtype_index!(
             @handle_debug
             @derives      [$($derives,)*]
@@ -144,7 +259,7 @@ macro_rules! newtype_index {
      @debug_format [$debug_format:tt]) => (
         impl ::std::fmt::Debug for $type {
             fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-                write!(fmt, $debug_format, self.0)
+                write!(fmt, $debug_format, self.as_u32())
             }
         }
     );
@@ -167,44 +282,17 @@ macro_rules! newtype_index {
             @debug_format [$debug_format]);
     );
 
-    // Handle the case where someone wants to make the internal field public
-    (@type         [$type:ident]
-     @max          [$max:expr]
-     @debug_format [$debug_format:tt]
-                   pub idx
-                   $($tokens:tt)*) => (
-        newtype_index!(
-            @pub          [pub]
-            @type         [$type]
-            @max          [$max]
-            @debug_format [$debug_format]
-                          $($tokens)*);
-    );
-
-    // The default case is that the internal field is private
-    (@type         [$type:ident]
-     @max          [$max:expr]
-     @debug_format [$debug_format:tt]
-                   $($tokens:tt)*) => (
-        newtype_index!(
-            @pub          []
-            @type         [$type]
-            @max          [$max]
-            @debug_format [$debug_format]
-                          $($tokens)*);
-    );
-
     // Append comma to end of derives list if it's missing
-    (@pub          [$($pub:tt)*]
-     @type         [$type:ident]
+    (@type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    derive [$($derives:ident),*]
                    $($tokens:tt)*) => (
         newtype_index!(
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           derive [$($derives,)*]
                           $($tokens)*);
@@ -212,154 +300,154 @@ macro_rules! newtype_index {
 
     // By not including the @derives marker in this list nor in the default args, we can force it
     // to come first if it exists. When encodable is custom, just use the derives list as-is.
-    (@pub          [$($pub:tt)*]
-     @type         [$type:ident]
+    (@type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    derive [$($derives:ident,)+]
                    ENCODABLE = custom
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)+]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
 
     // By not including the @derives marker in this list nor in the default args, we can force it
     // to come first if it exists. When encodable isn't custom, add serialization traits by default.
-    (@pub          [$($pub:tt)*]
-     @type         [$type:ident]
+    (@type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    derive [$($derives:ident,)+]
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)+ RustcDecodable, RustcEncodable,]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
 
     // The case where no derives are added, but encodable is overridden. Don't
     // derive serialization traits
-    (@pub          [$($pub:tt)*]
-     @type         [$type:ident]
+    (@type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    ENCODABLE = custom
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      []
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
 
     // The case where no derives are added, add serialization derives by default
-    (@pub          [$($pub:tt)*]
-     @type         [$type:ident]
+    (@type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [RustcDecodable, RustcEncodable,]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
 
     // Rewrite final without comma to one that includes comma
     (@derives      [$($derives:ident,)*]
-     @pub          [$($pub:tt)*]
      @type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $name:ident = $constant:expr) => (
         newtype_index!(
             @derives      [$($derives,)*]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $name = $constant,);
     );
 
     // Rewrite final const without comma to one that includes comma
     (@derives      [$($derives:ident,)*]
-     @pub          [$($pub:tt)*]
      @type         [$type:ident]
      @max          [$_max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $(#[doc = $doc:expr])*
                    const $name:ident = $constant:expr) => (
         newtype_index!(
             @derives      [$($derives,)*]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $(#[doc = $doc])* const $name = $constant,);
     );
 
     // Replace existing default for max
     (@derives      [$($derives:ident,)*]
-     @pub          [$($pub:tt)*]
      @type         [$type:ident]
      @max          [$_max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    MAX = $max:expr,
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)*]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
 
     // Replace existing default for debug_format
     (@derives      [$($derives:ident,)*]
-     @pub          [$($pub:tt)*]
      @type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$_debug_format:tt]
                    DEBUG_FORMAT = $debug_format:tt,
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)*]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
 
     // Assign a user-defined constant
     (@derives      [$($derives:ident,)*]
-     @pub          [$($pub:tt)*]
      @type         [$type:ident]
      @max          [$max:expr]
+     @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $(#[doc = $doc:expr])*
                    const $name:ident = $constant:expr,
                    $($tokens:tt)*) => (
         $(#[doc = $doc])*
-        pub const $name: $type = $type($constant);
+        pub const $name: $type = $type::from_u32_const($constant);
         newtype_index!(
             @derives      [$($derives,)*]
-            @pub          [$($pub)*]
             @type         [$type]
             @max          [$max]
+            @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
     );
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index c70a0abe8c7e4..215c44dec6913 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -217,6 +217,14 @@ impl_stable_hash_via_hash!(i128);
 impl_stable_hash_via_hash!(char);
 impl_stable_hash_via_hash!(());
 
+impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        self.get().hash_stable(ctx, hasher)
+    }
+}
+
 impl<CTX> HashStable<CTX> for f32 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 175422975e006..57c00f252ef16 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -183,8 +183,13 @@ fn test_env_with_pool<F>(
     });
 }
 
-const D1: ty::DebruijnIndex = ty::INNERMOST;
-const D2: ty::DebruijnIndex = D1.shifted_in(1);
+fn d1() -> ty::DebruijnIndex {
+    ty::INNERMOST
+}
+
+fn d2() -> ty::DebruijnIndex {
+    d1().shifted_in(1)
+}
 
 impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
     pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -337,7 +342,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
     }
 
     pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> {
-        let r = self.re_late_bound_with_debruijn(id, D1);
+        let r = self.re_late_bound_with_debruijn(id, d1());
         self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
     }
 
@@ -494,7 +499,7 @@ fn subst_ty_renumber_bound() {
 
         // t_expected = fn(&'a isize)
         let t_expected = {
-            let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2);
+            let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
             env.t_fn(&[t_ptr_bound2], env.t_nil())
         };
 
@@ -531,7 +536,7 @@ fn subst_ty_renumber_some_bounds() {
         //
         // but not that the Debruijn index is different in the different cases.
         let t_expected = {
-            let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2);
+            let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
             env.t_pair(t_rptr_bound1, env.t_fn(&[t_rptr_bound2], env.t_nil()))
         };
 
@@ -559,10 +564,10 @@ fn escaping() {
         let t_rptr_free1 = env.t_rptr_free(1);
         assert!(!t_rptr_free1.has_escaping_regions());
 
-        let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, D1);
+        let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1());
         assert!(t_rptr_bound1.has_escaping_regions());
 
-        let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2);
+        let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
         assert!(t_rptr_bound2.has_escaping_regions());
 
         // t_fn = fn(A)
@@ -578,7 +583,7 @@ fn escaping() {
 #[test]
 fn subst_region_renumber_region() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
-        let re_bound1 = env.re_late_bound_with_debruijn(1, D1);
+        let re_bound1 = env.re_late_bound_with_debruijn(1, d1());
 
         // type t_source<'a> = fn(&'a isize)
         let t_source = {
@@ -593,7 +598,7 @@ fn subst_region_renumber_region() {
         //
         // but not that the Debruijn index is different in the different cases.
         let t_expected = {
-            let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2);
+            let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
             env.t_fn(&[t_rptr_bound2], env.t_nil())
         };
 
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index a0b0aabf73e02..3f8cd03660c43 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -16,7 +16,6 @@ use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
 use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::DiagnosticBuilder;
 use syntax_pos::Span;
diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs
index 28da1b2d73357..91008e8f9690e 100644
--- a/src/librustc_mir/borrow_check/location.rs
+++ b/src/librustc_mir/borrow_check/location.rs
@@ -27,7 +27,11 @@ crate struct LocationTable {
     statements_before_block: IndexVec<BasicBlock, usize>,
 }
 
-newtype_index!(LocationIndex { DEBUG_FORMAT = "LocationIndex({})" });
+newtype_index! {
+    pub struct LocationIndex {
+        DEBUG_FORMAT = "LocationIndex({})"
+    }
+}
 
 #[derive(Copy, Clone, Debug)]
 crate enum RichLocation {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 497e8e07853fb..290c703238805 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -12,7 +12,6 @@ use core::unicode::property::Pattern_White_Space;
 use rustc::mir::*;
 use rustc::ty;
 use rustc_errors::DiagnosticBuilder;
-use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 
 use borrow_check::MirBorrowckCtxt;
diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs
index 4cb92262ff085..817b215225b42 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs
@@ -98,6 +98,14 @@ impl fmt::Debug for OutlivesConstraint {
     }
 }
 
-newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" });
+newtype_index! {
+    pub struct ConstraintIndex {
+        DEBUG_FORMAT = "ConstraintIndex({})"
+    }
+}
 
-newtype_index!(ConstraintSccIndex { DEBUG_FORMAT = "ConstraintSccIndex({})" });
+newtype_index! {
+    pub struct ConstraintSccIndex {
+        DEBUG_FORMAT = "ConstraintSccIndex({})"
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs
index 8eb052f88e124..465707ecc17dd 100644
--- a/src/librustc_mir/borrow_check/nll/facts.rs
+++ b/src/librustc_mir/borrow_check/nll/facts.rs
@@ -100,18 +100,6 @@ impl Atom for LocationIndex {
     }
 }
 
-impl From<usize> for LocationIndex {
-    fn from(i: usize) -> LocationIndex {
-        LocationIndex::new(i)
-    }
-}
-
-impl From<LocationIndex> for usize {
-    fn from(vid: LocationIndex) -> usize {
-        Idx::index(vid)
-    }
-}
-
 struct FactWriter<'w> {
     location_table: &'w LocationTable,
     dir: &'w Path,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
index dd508084d7dec..34e893d2a59f2 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
@@ -15,7 +15,6 @@
 use super::*;
 use borrow_check::nll::constraints::OutlivesConstraint;
 use dot::{self, IntoCow};
-use rustc_data_structures::indexed_vec::Idx;
 use std::borrow::Cow;
 use std::io::{self, Write};
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index ae5d57906739b..3dafab2f5a9f4 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -123,13 +123,17 @@ impl RegionValueElements {
 
 /// A single integer representing a `Location` in the MIR control-flow
 /// graph. Constructed efficiently from `RegionValueElements`.
-newtype_index!(PointIndex { DEBUG_FORMAT = "PointIndex({})" });
+newtype_index! {
+    pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" }
+}
 
 /// A single integer representing a (non-zero) `UniverseIndex`.
 /// Computed just by subtracting one from `UniverseIndex`; this is
 /// because the `0` value for `UniverseIndex` represents the root
 /// universe, and we don't need/want a bit for that one.
-newtype_index!(PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" });
+newtype_index! {
+    pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }
+}
 
 /// An individual element in a region value -- the value of a
 /// particular region variable consists of a set of these elements.
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
index 15affbbc27a20..467554dc38a67 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
@@ -97,6 +97,6 @@ impl NllLivenessMap {
 /// compute liveness information. For many locals, we are able to
 /// skip liveness information: for example, those variables whose
 /// types contain no regions.
-newtype_index!(
-    LiveVar
-);
+newtype_index! {
+    pub struct LiveVar { .. }
+}
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
index 73d285c2f2eb8..4b39d58cd96a8 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
@@ -48,7 +48,9 @@ struct Appearance {
     next: Option<AppearanceIndex>,
 }
 
-newtype_index!(AppearanceIndex);
+newtype_index! {
+    pub struct AppearanceIndex { .. }
+}
 
 impl vll::LinkElem for Appearance {
     type LinkIndex = AppearanceIndex;
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 61c99832448c5..82158acc9e6ab 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -42,7 +42,6 @@ use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::indexed_vec::Idx;
 
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
index deb972ee04611..8ffce9c94926f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
@@ -20,7 +20,7 @@ use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc::ty::subst::Kind;
 use rustc::ty::{self, CanonicalTy, CanonicalVar, RegionVid, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::indexed_vec::IndexVec;
 use std::mem;
 
 pub(super) fn sub_types<'tcx>(
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index f178ea8bdbab1..322a6977bedd0 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -402,7 +402,9 @@ struct CFG<'tcx> {
     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
 }
 
-newtype_index!(ScopeId);
+newtype_index! {
+    pub struct ScopeId { .. }
+}
 
 ///////////////////////////////////////////////////////////////////////////
 /// The `BlockAnd` "monad" packages up the new basic block along with a
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 8e99a45c87fdc..38e0854bcd61e 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -95,7 +95,6 @@ use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::mir::*;
 use syntax_pos::{Span};
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::fx::FxHashMap;
 
 #[derive(Debug)]
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 92ddd8777f733..154830c2e77e0 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -19,7 +19,7 @@ use rustc::mir;
 use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
 use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc::ty::subst::Subst;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::IndexVec;
 
 use syntax::ast::Mutability;
 use syntax::source_map::Span;
diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs
index d97c0c9b43019..1dc91cd05b33e 100644
--- a/src/librustc_mir/dataflow/at_location.rs
+++ b/src/librustc_mir/dataflow/at_location.rs
@@ -13,7 +13,6 @@
 
 use rustc::mir::{BasicBlock, Location};
 use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet, Iter};
-use rustc_data_structures::indexed_vec::Idx;
 
 use dataflow::{BitDenotation, BlockSets, DataflowResults};
 use dataflow::move_paths::{HasMoveData, MovePathIndex};
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 1d35bb85a21a1..2b5d26c748704 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -13,7 +13,6 @@
 use syntax::ast::NodeId;
 use rustc::mir::{BasicBlock, Mir};
 use rustc_data_structures::bitslice::bits_to_string;
-use rustc_data_structures::indexed_vec::Idx;
 
 use dot;
 use dot::IntoCow;
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 4093a6304b360..461285ff9bc10 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -16,7 +16,7 @@ use std::convert::TryInto;
 
 use rustc::{mir, ty};
 use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
-use rustc_data_structures::indexed_vec::Idx;
+
 use rustc::mir::interpret::{
     GlobalId, AllocId,
     ConstValue, Pointer, Scalar, ScalarMaybeUndef,
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 51a4294452719..d01593ca5e91c 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -18,7 +18,6 @@ use rustc::ich::StableHashingContext;
 use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 
 use rustc::mir::interpret::{
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index be04f75c7260c..d4024981c3754 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -24,6 +24,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
 #![feature(core_intrinsics)]
+#![feature(const_fn)]
 #![feature(decl_macro)]
 #![cfg_attr(stage0, feature(macro_vis_matcher))]
 #![feature(exhaustive_patterns)]
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index e2b1a255eaca2..4d19e9dfbf98a 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -26,7 +26,7 @@ use interpret::{self, Value, OpTy, MemoryKind};
 use transform::{MirPass, MirSource};
 use syntax::source_map::{Span, DUMMY_SP};
 use rustc::ty::subst::Substs;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::ParamEnv;
 use rustc::ty::layout::{
     LayoutOf, TyLayout, LayoutError,
@@ -133,7 +133,6 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
         self.ecx.tcx.span = source_info.span;
         let lint_root = match self.mir.source_scope_local_data {
             ClearCrossCrate::Set(ref ivs) => {
-                use rustc_data_structures::indexed_vec::Idx;
                 //FIXME(#51314): remove this check
                 if source_info.scope.index() >= ivs.len() {
                     return None;
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 225de03a32965..bf538112e41ed 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -19,7 +19,6 @@ use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSet;
-use rustc_data_structures::indexed_vec::Idx;
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
 use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 050901b9b508a..81fc235c23346 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -16,7 +16,7 @@
 
 use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_set::IdxSet;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index eda7de0fd79d4..9faaeea3f5b70 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -15,7 +15,6 @@ use syntax_pos::Span;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir, Location};
 use rustc_data_structures::indexed_set::IdxSet;
-use rustc_data_structures::indexed_vec::Idx;
 use transform::{MirPass, MirSource};
 
 use dataflow::{do_dataflow, DebugFormatted};
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 22e2b1b0b09c9..0b883f68bff40 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -15,8 +15,6 @@ use rustc::ty::TyCtxt;
 use std::fmt::Debug;
 use std::io::{self, Write};
 
-use rustc_data_structures::indexed_vec::Idx;
-
 use super::pretty::dump_mir_def_ids;
 
 /// Write a graphviz DOT graph of a list of MIRs.
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 804aad3c0ecce..65dd71de1443f 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -25,10 +25,11 @@ use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc::ty::wf::object_region_bounds;
 use rustc_target::spec::abi;
+use std::collections::BTreeSet;
 use std::slice;
 use require_c_abi_if_variadic;
 use util::common::ErrorReported;
-use util::nodemap::{FxHashSet, FxHashMap};
+use util::nodemap::FxHashMap;
 use errors::{FatalError, DiagnosticId};
 use lint;
 
@@ -996,7 +997,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
             return tcx.types.err;
         }
 
-        let mut associated_types = FxHashSet::default();
+        // use a btreeset to keep output in a more consistent order
+        let mut associated_types = BTreeSet::default();
+
         for tr in traits::supertraits(tcx, principal) {
             associated_types.extend(tcx.associated_items(tr.def_id())
                 .filter(|item| item.kind == ty::AssociatedKind::Type)
diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index 60bb5a0fec2cd..416be50bfe9ea 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -361,6 +361,18 @@ impl Decodable for u32 {
     }
 }
 
+impl Encodable for ::std::num::NonZeroU32 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_u32(self.get())
+    }
+}
+
+impl Decodable for ::std::num::NonZeroU32 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+        d.read_u32().map(|d| ::std::num::NonZeroU32::new(d).unwrap())
+    }
+}
+
 impl Encodable for u64 {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u64(*self)
@@ -895,3 +907,4 @@ impl<T: UseSpecializedDecodable> Decodable for T {
 impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {}
 impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {}
 impl<T: Decodable> UseSpecializedDecodable for Box<T> {}
+