From 6fef118bc0b99e3e54aef3f4efa5abb55b2f6476 Mon Sep 17 00:00:00 2001
From: Oliver 'ker' Schneider <rust19446194516@oli-obk.de>
Date: Sat, 16 Jan 2016 16:03:09 +0100
Subject: [PATCH] use a newtype for the variant discriminant instead of u64

---
 src/librustc_trans/trans/_match.rs            | 19 ++--
 src/librustc_trans/trans/adt.rs               | 88 ++++++++++---------
 src/librustc_trans/trans/base.rs              | 29 +++---
 src/librustc_trans/trans/build.rs             |  7 +-
 src/librustc_trans/trans/callee.rs            | 11 +--
 src/librustc_trans/trans/closure.rs           |  5 +-
 src/librustc_trans/trans/common.rs            |  8 +-
 src/librustc_trans/trans/consts.rs            | 11 +--
 .../trans/debuginfo/metadata.rs               |  8 +-
 src/librustc_trans/trans/disr.rs              | 49 +++++++++++
 src/librustc_trans/trans/expr.rs              | 15 ++--
 src/librustc_trans/trans/foreign.rs           |  3 +-
 src/librustc_trans/trans/intrinsic.rs         |  3 +-
 src/librustc_trans/trans/mir/block.rs         |  3 +-
 src/librustc_trans/trans/mir/lvalue.rs        |  3 +-
 src/librustc_trans/trans/mir/rvalue.rs        |  5 +-
 src/librustc_trans/trans/mod.rs               |  2 +
 src/librustc_trans/trans/monomorphize.rs      |  3 +-
 src/librustc_typeck/check/mod.rs              |  2 +-
 19 files changed, 173 insertions(+), 101 deletions(-)
 create mode 100644 src/librustc_trans/trans/disr.rs

diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index f46a7ea67b5..6c1a31738af 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -215,6 +215,7 @@ use trans::expr::{self, Dest};
 use trans::monomorphize;
 use trans::tvec;
 use trans::type_of;
+use trans::Disr;
 use middle::ty::{self, Ty};
 use session::config::NoDebugInfo;
 use util::common::indenter;
@@ -249,7 +250,7 @@ impl<'a> ConstantExpr<'a> {
 enum Opt<'a, 'tcx> {
     ConstantValue(ConstantExpr<'a>, DebugLoc),
     ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>, DebugLoc),
-    Variant(ty::Disr, Rc<adt::Repr<'tcx>>, DefId, DebugLoc),
+    Variant(Disr, Rc<adt::Repr<'tcx>>, DefId, DebugLoc),
     SliceLengthEqual(usize, DebugLoc),
     SliceLengthGreaterOrEqual(/* prefix length */ usize,
                               /* suffix length */ usize,
@@ -670,7 +671,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 match opt_def {
                     Some(def::DefVariant(enum_id, var_id, _)) => {
                         let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id);
-                        Variant(variant.disr_val,
+                        Variant(Disr::from(variant.disr_val),
                                 adt::represent_node(bcx, cur.id),
                                 var_id,
                                 debug_loc)
@@ -704,7 +705,7 @@ struct ExtractedBlock<'blk, 'tcx: 'blk> {
 
 fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     repr: &adt::Repr<'tcx>,
-                                    disr_val: ty::Disr,
+                                    disr_val: Disr,
                                     val: MatchInput)
                                     -> ExtractedBlock<'blk, 'tcx> {
     let _icx = push_ctxt("match::extract_variant_args");
@@ -1189,7 +1190,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     };
     let adt_vals = if any_irrefutable_adt_pat(bcx.tcx(), m, col) {
         let repr = adt::represent_type(bcx.ccx(), left_ty);
-        let arg_count = adt::num_args(&*repr, 0);
+        let arg_count = adt::num_args(&*repr, Disr(0));
         let (arg_count, struct_val) = if type_is_sized(bcx.tcx(), left_ty) {
             (arg_count, val.val)
         } else {
@@ -1201,7 +1202,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         };
         let mut field_vals: Vec<ValueRef> = (0..arg_count).map(|ix|
             // By definition, these are all sized
-            adt::trans_field_ptr(bcx, &*repr, adt::MaybeSizedValue::sized(struct_val), 0, ix)
+            adt::trans_field_ptr(bcx, &*repr, adt::MaybeSizedValue::sized(struct_val), Disr(0), ix)
         ).collect();
 
         match left_ty.sty {
@@ -1217,7 +1218,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 let meta = Load(bcx, expr::get_meta(bcx, val.val));
                 let struct_val = adt::MaybeSizedValue::unsized_(struct_val, meta);
 
-                let data = adt::trans_field_ptr(bcx, &*repr, struct_val, 0, arg_count);
+                let data = adt::trans_field_ptr(bcx, &*repr, struct_val, Disr(0), arg_count);
                 Store(bcx, data, expr::get_dataptr(bcx, scratch));
                 Store(bcx, meta, expr::get_meta(bcx, scratch));
                 field_vals.push(scratch);
@@ -1855,7 +1856,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id);
                     let args = extract_variant_args(bcx,
                                                     &*repr,
-                                                    vinfo.disr_val,
+                                                    Disr::from(vinfo.disr_val),
                                                     val);
                     if let Some(ref sub_pat) = *sub_pats {
                         for (i, &argval) in args.vals.iter().enumerate() {
@@ -1878,7 +1879,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             let val = adt::MaybeSizedValue::sized(val.val);
                             for (i, elem) in elems.iter().enumerate() {
                                 let fldptr = adt::trans_field_ptr(bcx, &*repr,
-                                                                  val, 0, i);
+                                                                  val, Disr(0), i);
                                 bcx = bind_irrefutable_pat(
                                     bcx,
                                     &**elem,
@@ -1937,7 +1938,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let repr = adt::represent_node(bcx, pat.id);
             let val = adt::MaybeSizedValue::sized(val.val);
             for (i, elem) in elems.iter().enumerate() {
-                let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i);
+                let fldptr = adt::trans_field_ptr(bcx, &*repr, val, Disr(0), i);
                 bcx = bind_irrefutable_pat(
                     bcx,
                     &**elem,
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index d22d619b962..59487c0362c 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -42,6 +42,7 @@
 //!   taken to it, implementing them for Rust seems difficult.
 
 pub use self::Repr::*;
+use super::Disr;
 
 use std;
 use std::rc::Rc;
@@ -50,7 +51,6 @@ use llvm::{ValueRef, True, IntEQ, IntNE};
 use back::abi::FAT_PTR_ADDR;
 use middle::subst;
 use middle::ty::{self, Ty};
-use middle::ty::Disr;
 use syntax::ast;
 use syntax::attr;
 use syntax::attr::IntType;
@@ -308,12 +308,12 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             if !dtor && cases.iter().all(|c| c.tys.is_empty()) {
                 // All bodies empty -> intlike
-                let discrs: Vec<u64> = cases.iter().map(|c| c.discr).collect();
+                let discrs: Vec<_> = cases.iter().map(|c| Disr::from(c.discr)).collect();
                 let bounds = IntBounds {
-                    ulo: *discrs.iter().min().unwrap(),
-                    uhi: *discrs.iter().max().unwrap(),
-                    slo: discrs.iter().map(|n| *n as i64).min().unwrap(),
-                    shi: discrs.iter().map(|n| *n as i64).max().unwrap()
+                    ulo: discrs.iter().min().unwrap().0,
+                    uhi: discrs.iter().max().unwrap().0,
+                    slo: discrs.iter().map(|n| n.0 as i64).min().unwrap(),
+                    shi: discrs.iter().map(|n| n.0 as i64).max().unwrap()
                 };
                 return mk_cenum(cx, hint, &bounds);
             }
@@ -321,7 +321,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // Since there's at least one
             // non-empty body, explicit discriminants should have
             // been rejected by a checker before this point.
-            if !cases.iter().enumerate().all(|(i,c)| c.discr == (i as Disr)) {
+            if !cases.iter().enumerate().all(|(i,c)| c.discr == Disr::from(i)) {
                 cx.sess().bug(&format!("non-C-like enum {} with specified \
                                         discriminants",
                                        cx.tcx().item_path_str(def.did)));
@@ -347,7 +347,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         match cases[discr].find_ptr(cx) {
                             Some(ref df) if df.len() == 1 && st.fields.len() == 1 => {
                                 return RawNullablePointer {
-                                    nndiscr: discr as Disr,
+                                    nndiscr: Disr::from(discr),
                                     nnty: st.fields[0],
                                     nullfields: cases[1 - discr].tys.clone()
                                 };
@@ -356,7 +356,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                 discrfield.push(0);
                                 discrfield.reverse();
                                 return StructWrappedNullablePointer {
-                                    nndiscr: discr as Disr,
+                                    nndiscr: Disr::from(discr),
                                     nonnull: st,
                                     discrfield: discrfield,
                                     nullfields: cases[1 - discr].tys.clone()
@@ -564,7 +564,7 @@ fn get_cases<'tcx>(tcx: &ty::ctxt<'tcx>,
         let field_tys = vi.fields.iter().map(|field| {
             monomorphize::field_ty(tcx, substs, field)
         }).collect();
-        Case { discr: vi.disr_val, tys: field_tys }
+        Case { discr: Disr::from(vi.disr_val), tys: field_tys }
     }).collect()
 }
 
@@ -605,8 +605,8 @@ fn mk_cenum<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                       -> Repr<'tcx> {
     let it = range_to_inttype(cx, hint, bounds);
     match it {
-        attr::SignedInt(_) => CEnum(it, bounds.slo as Disr, bounds.shi as Disr),
-        attr::UnsignedInt(_) => CEnum(it, bounds.ulo, bounds.uhi)
+        attr::SignedInt(_) => CEnum(it, Disr(bounds.slo as u64), Disr(bounds.shi as u64)),
+        attr::UnsignedInt(_) => CEnum(it, Disr(bounds.ulo), Disr(bounds.uhi))
     }
 }
 
@@ -923,11 +923,11 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
         CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
         General(ity, ref cases, _) => {
             let ptr = StructGEP(bcx, scrutinee, 0);
-            load_discr(bcx, ity, ptr, 0, (cases.len() - 1) as Disr)
+            load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1))
         }
         Univariant(..) => C_u8(bcx.ccx(), 0),
         RawNullablePointer { nndiscr, nnty, .. } =>  {
-            let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
+            let cmp = if nndiscr == Disr(0) { IntEQ } else { IntNE };
             let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty);
             ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty), DebugLoc::None)
         }
@@ -945,7 +945,7 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
                                     scrutinee: ValueRef) -> ValueRef {
     let llptrptr = GEPi(bcx, scrutinee, &discrfield[..]);
     let llptr = Load(bcx, llptrptr);
-    let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
+    let cmp = if nndiscr == Disr(0) { IntEQ } else { IntNE };
     ICmp(bcx, cmp, llptr, C_null(val_ty(llptr)), DebugLoc::None)
 }
 
@@ -957,10 +957,10 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     let bits = machine::llbitsize_of_real(bcx.ccx(), llty);
     assert!(bits <= 64);
     let  bits = bits as usize;
-    let mask = (!0u64 >> (64 - bits)) as Disr;
+    let mask = Disr(!0u64 >> (64 - bits));
     // For a (max) discr of -1, max will be `-1 as usize`, which overflows.
     // However, that is fine here (it would still represent the full range),
-    if (max.wrapping_add(1)) & mask == min & mask {
+    if max.wrapping_add(Disr(1)) & mask == min & mask {
         // i.e., if the range is everything.  The lo==hi case would be
         // rejected by the LLVM verifier (it would mean either an
         // empty set, which is impossible, or the entire range of the
@@ -969,7 +969,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     } else {
         // llvm::ConstantRange can deal with ranges that wrap around,
         // so an overflow on (max + 1) is fine.
-        LoadRangeAssert(bcx, ptr, min, (max.wrapping_add(1)), /* signed: */ True)
+        LoadRangeAssert(bcx, ptr, min, max.wrapping_add(Disr(1)), /* signed: */ True)
     }
 }
 
@@ -981,18 +981,18 @@ pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
                               -> ValueRef {
     match *r {
         CEnum(ity, _, _) => {
-            C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true)
+            C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true)
         }
         General(ity, _, _) => {
-            C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true)
+            C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true)
         }
         Univariant(..) => {
             bcx.ccx().sess().bug("no cases for univariants or structs")
         }
         RawNullablePointer { .. } |
         StructWrappedNullablePointer { .. } => {
-            assert!(discr == 0 || discr == 1);
-            C_bool(bcx.ccx(), discr != 0)
+            assert!(discr == Disr(0) || discr == Disr(1));
+            C_bool(bcx.ccx(), discr != Disr(0))
         }
     }
 }
@@ -1004,20 +1004,20 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
     match *r {
         CEnum(ity, min, max) => {
             assert_discr_in_range(ity, min, max, discr);
-            Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
+            Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true),
                   val);
         }
         General(ity, ref cases, dtor) => {
             if dtor_active(dtor) {
                 let ptr = trans_field_ptr(bcx, r, MaybeSizedValue::sized(val), discr,
-                                          cases[discr as usize].fields.len() - 2);
+                                          cases[discr.0 as usize].fields.len() - 2);
                 Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED), ptr);
             }
-            Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
+            Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true),
                   StructGEP(bcx, val, 0));
         }
         Univariant(ref st, dtor) => {
-            assert_eq!(discr, 0);
+            assert_eq!(discr, Disr(0));
             if dtor_active(dtor) {
                 Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED),
                       StructGEP(bcx, val, st.fields.len() - 1));
@@ -1041,8 +1041,14 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
 
 fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) {
     match ity {
-        attr::UnsignedInt(_) => assert!(min <= discr && discr <= max),
-        attr::SignedInt(_) => assert!(min as i64 <= discr as i64 && discr as i64 <= max as i64)
+        attr::UnsignedInt(_) => {
+            assert!(min <= discr);
+            assert!(discr <= max)
+        },
+        attr::SignedInt(_) => {
+            assert!(min.0 as i64 <= discr.0 as i64);
+            assert!(discr.0 as i64 <= max.0 as i64);
+        },
     }
 }
 
@@ -1052,11 +1058,11 @@ pub fn num_args(r: &Repr, discr: Disr) -> usize {
     match *r {
         CEnum(..) => 0,
         Univariant(ref st, dtor) => {
-            assert_eq!(discr, 0);
+            assert_eq!(discr, Disr(0));
             st.fields.len() - (if dtor_active(dtor) { 1 } else { 0 })
         }
         General(_, ref cases, dtor) => {
-            cases[discr as usize].fields.len() - 1 - (if dtor_active(dtor) { 1 } else { 0 })
+            cases[discr.0 as usize].fields.len() - 1 - (if dtor_active(dtor) { 1 } else { 0 })
         }
         RawNullablePointer { nndiscr, ref nullfields, .. } => {
             if discr == nndiscr { 1 } else { nullfields.len() }
@@ -1079,11 +1085,11 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
             bcx.ccx().sess().bug("element access in C-like enum")
         }
         Univariant(ref st, _dtor) => {
-            assert_eq!(discr, 0);
+            assert_eq!(discr, Disr(0));
             struct_field_ptr(bcx, st, val, ix, false)
         }
         General(_, ref cases, _) => {
-            struct_field_ptr(bcx, &cases[discr as usize], val, ix + 1, true)
+            struct_field_ptr(bcx, &cases[discr.0 as usize], val, ix + 1, true)
         }
         RawNullablePointer { nndiscr, ref nullfields, .. } |
         StructWrappedNullablePointer { nndiscr, ref nullfields, .. } if discr != nndiscr => {
@@ -1326,12 +1332,12 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
         CEnum(ity, min, max) => {
             assert_eq!(vals.len(), 0);
             assert_discr_in_range(ity, min, max, discr);
-            C_integral(ll_inttype(ccx, ity), discr as u64, true)
+            C_integral(ll_inttype(ccx, ity), discr.0, true)
         }
         General(ity, ref cases, _) => {
-            let case = &cases[discr as usize];
+            let case = &cases[discr.0 as usize];
             let (max_sz, _) = union_size_and_align(&cases[..]);
-            let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true);
+            let lldiscr = C_integral(ll_inttype(ccx, ity), discr.0 as u64, true);
             let mut f = vec![lldiscr];
             f.extend_from_slice(vals);
             let mut contents = build_const_struct(ccx, case, &f[..]);
@@ -1339,7 +1345,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
             C_struct(ccx, &contents[..], false)
         }
         Univariant(ref st, _dro) => {
-            assert!(discr == 0);
+            assert_eq!(discr, Disr(0));
             let contents = build_const_struct(ccx, st, vals);
             C_struct(ccx, &contents[..], st.packed)
         }
@@ -1444,17 +1450,17 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef) -> Disr {
     match *r {
         CEnum(ity, _, _) => {
             match ity {
-                attr::SignedInt(..) => const_to_int(val) as Disr,
-                attr::UnsignedInt(..) => const_to_uint(val) as Disr
+                attr::SignedInt(..) => Disr(const_to_int(val) as u64),
+                attr::UnsignedInt(..) => Disr(const_to_uint(val)),
             }
         }
         General(ity, _, _) => {
             match ity {
-                attr::SignedInt(..) => const_to_int(const_get_elt(ccx, val, &[0])) as Disr,
-                attr::UnsignedInt(..) => const_to_uint(const_get_elt(ccx, val, &[0])) as Disr
+                attr::SignedInt(..) => Disr(const_to_int(const_get_elt(ccx, val, &[0])) as u64),
+                attr::UnsignedInt(..) => Disr(const_to_uint(const_get_elt(ccx, val, &[0])))
             }
         }
-        Univariant(..) => 0,
+        Univariant(..) => Disr(0),
         RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
             ccx.sess().bug("const discrim access of non c-like enum")
         }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index ea4259f8262..3909cb2df23 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -85,6 +85,7 @@ use trans::type_::Type;
 use trans::type_of;
 use trans::type_of::*;
 use trans::value::Value;
+use trans::Disr;
 use util::common::indenter;
 use util::sha2::Sha256;
 use util::nodemap::{NodeMap, NodeSet};
@@ -489,7 +490,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
         for (i, field) in variant.fields.iter().enumerate() {
             let arg = monomorphize::field_ty(tcx, substs, field);
             cx = f(cx,
-                   adt::trans_field_ptr(cx, repr, av, variant.disr_val, i),
+                   adt::trans_field_ptr(cx, repr, av, Disr::from(variant.disr_val), i),
                    arg);
         }
         return cx;
@@ -509,7 +510,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
             let repr = adt::represent_type(cx.ccx(), t);
             let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
             for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
-                let llfld_a = adt::trans_field_ptr(cx, &*repr, value, discr, i);
+                let llfld_a = adt::trans_field_ptr(cx, &*repr, value, Disr::from(discr), i);
 
                 let val = if common::type_is_sized(cx.tcx(), field_ty) {
                     llfld_a
@@ -525,7 +526,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
         ty::TyClosure(_, ref substs) => {
             let repr = adt::represent_type(cx.ccx(), t);
             for (i, upvar_ty) in substs.upvar_tys.iter().enumerate() {
-                let llupvar = adt::trans_field_ptr(cx, &*repr, value, 0, i);
+                let llupvar = adt::trans_field_ptr(cx, &*repr, value, Disr(0), i);
                 cx = f(cx, llupvar, upvar_ty);
             }
         }
@@ -541,7 +542,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
         ty::TyTuple(ref args) => {
             let repr = adt::represent_type(cx.ccx(), t);
             for (i, arg) in args.iter().enumerate() {
-                let llfld_a = adt::trans_field_ptr(cx, &*repr, value, 0, i);
+                let llfld_a = adt::trans_field_ptr(cx, &*repr, value, Disr(0), i);
                 cx = f(cx, llfld_a, *arg);
             }
         }
@@ -588,7 +589,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
                         let variant_cx = fcx.new_temp_block(&format!("enum-iter-variant-{}",
                                                                      &variant.disr_val
                                                                              .to_string()));
-                        let case_val = adt::trans_case(cx, &*repr, variant.disr_val);
+                        let case_val = adt::trans_case(cx, &*repr, Disr::from(variant.disr_val));
                         AddCase(llswitch, case_val, variant_cx.llbb);
                         let variant_cx = iter_variant(variant_cx,
                                                       &*repr,
@@ -720,8 +721,8 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     continue;
                 }
 
-                let src_f = adt::trans_field_ptr(bcx, &src_repr, src, 0, i);
-                let dst_f = adt::trans_field_ptr(bcx, &dst_repr, dst, 0, i);
+                let src_f = adt::trans_field_ptr(bcx, &src_repr, src, Disr(0), i);
+                let dst_f = adt::trans_field_ptr(bcx, &dst_repr, dst, Disr(0), i);
                 if src_fty == dst_fty {
                     memcpy_ty(bcx, dst_f, src_f, src_fty);
                 } else {
@@ -1022,11 +1023,11 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) ->
     }
 
     let val = if t.is_bool() {
-        LoadRangeAssert(cx, ptr, 0, 2, llvm::False)
+        LoadRangeAssert(cx, ptr, Disr(0), Disr(2), llvm::False)
     } else if t.is_char() {
         // a char is a Unicode codepoint, and so takes values from 0
         // to 0x10FFFF inclusive only.
-        LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
+        LoadRangeAssert(cx, ptr, Disr(0), Disr(0x10FFFF + 1), llvm::False)
     } else if (t.is_region_ptr() || t.is_unique()) && !common::type_is_fat_ptr(cx.tcx(), t) {
         LoadNonNull(cx, ptr)
     } else {
@@ -2111,7 +2112,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                     ctor_id: ast::NodeId,
-                                    disr: ty::Disr,
+                                    disr: Disr,
                                     param_substs: &'tcx Substs<'tcx>,
                                     llfndecl: ValueRef) {
     let _icx = push_ctxt("trans_enum_variant");
@@ -2121,7 +2122,7 @@ pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                                  ctor_ty: Ty<'tcx>,
-                                                 disr: ty::Disr,
+                                                 disr: Disr,
                                                  args: callee::CallArgs,
                                                  dest: expr::Dest,
                                                  debug_loc: DebugLoc)
@@ -2197,12 +2198,12 @@ pub fn trans_tuple_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                     llfndecl: ValueRef) {
     let _icx = push_ctxt("trans_tuple_struct");
 
-    trans_enum_variant_or_tuple_like_struct(ccx, ctor_id, 0, param_substs, llfndecl);
+    trans_enum_variant_or_tuple_like_struct(ccx, ctor_id, Disr(0), param_substs, llfndecl);
 }
 
 fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                      ctor_id: ast::NodeId,
-                                                     disr: ty::Disr,
+                                                     disr: Disr,
                                                      param_substs: &'tcx Substs<'tcx>,
                                                      llfndecl: ValueRef) {
     let ctor_ty = ccx.tcx().node_id_to_type(ctor_id);
@@ -2233,7 +2234,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
         let repr = adt::represent_type(ccx, result_ty.unwrap());
         let mut llarg_idx = fcx.arg_offset() as c_uint;
         for (i, arg_ty) in arg_tys.into_iter().enumerate() {
-            let lldestptr = adt::trans_field_ptr(bcx, &*repr, dest_val, disr, i);
+            let lldestptr = adt::trans_field_ptr(bcx, &*repr, dest_val, Disr::from(disr), i);
             if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
                 Store(bcx,
                       get_param(fcx.llfn, llarg_idx),
diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs
index 5a3fcc8d27f..89e58557179 100644
--- a/src/librustc_trans/trans/build.rs
+++ b/src/librustc_trans/trans/build.rs
@@ -21,6 +21,7 @@ use syntax::codemap::Span;
 use trans::builder::Builder;
 use trans::type_::Type;
 use trans::debuginfo::DebugLoc;
+use trans::Disr;
 
 use libc::{c_uint, c_char};
 
@@ -577,8 +578,8 @@ pub fn AtomicLoad(cx: Block, pointer_val: ValueRef, order: AtomicOrdering) -> Va
 }
 
 
-pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: u64,
-                       hi: u64, signed: llvm::Bool) -> ValueRef {
+pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: Disr,
+                       hi: Disr, signed: llvm::Bool) -> ValueRef {
     if cx.unreachable.get() {
         let ccx = cx.fcx.ccx;
         let ty = val_ty(pointer_val);
@@ -591,7 +592,7 @@ pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: u64,
             llvm::LLVMGetUndef(eltty.to_ref())
         }
     } else {
-        B(cx).load_range_assert(pointer_val, lo, hi, signed)
+        B(cx).load_range_assert(pointer_val, lo.0, hi.0, signed)
     }
 }
 
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index e3b7502b69c..c7ec1c09551 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -50,6 +50,7 @@ use trans::meth;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
+use trans::Disr;
 use middle::ty::{self, Ty, TypeFoldable};
 use middle::ty::MethodCall;
 use rustc_front::hir;
@@ -68,7 +69,7 @@ pub struct MethodData {
 pub enum CalleeData<'tcx> {
     // Constructor for enum variant/tuple-like-struct
     // i.e. Some, Ok
-    NamedTupleConstructor(ty::Disr),
+    NamedTupleConstructor(Disr),
 
     // Represents a (possibly monomorphized) top-level fn item or method
     // item. Note that this is just the fn-ptr and is not a Rust closure
@@ -151,7 +152,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
             } => {
                 Callee {
                     bcx: bcx,
-                    data: NamedTupleConstructor(0),
+                    data: NamedTupleConstructor(Disr(0)),
                     ty: expr_ty
                 }
             }
@@ -195,14 +196,14 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
 
                 Callee {
                     bcx: bcx,
-                    data: NamedTupleConstructor(vinfo.disr_val),
+                    data: NamedTupleConstructor(Disr::from(vinfo.disr_val)),
                     ty: expr_ty
                 }
             }
             def::DefStruct(_) => {
                 Callee {
                     bcx: bcx,
-                    data: NamedTupleConstructor(0),
+                    data: NamedTupleConstructor(Disr(0)),
                     ty: expr_ty
                 }
             }
@@ -863,7 +864,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
                     bcx,
                     field_type,
                     |srcval| {
-                        adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i)
+                        adt::trans_field_ptr(bcx, repr_ptr, srcval, Disr(0), i)
                     }).to_expr_datum();
                 bcx = trans_arg_datum(bcx,
                                       field_type,
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index ea9ca8f37b1..5bdfc099f08 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -26,6 +26,7 @@ use trans::declare;
 use trans::expr;
 use trans::monomorphize::{MonoId};
 use trans::type_of::*;
+use trans::Disr;
 use middle::ty;
 use session::config::FullDebugInfo;
 
@@ -242,7 +243,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     for (i, freevar) in freevars.iter().enumerate() {
         let datum = expr::trans_local_var(bcx, freevar.def);
         let upvar_slot_dest = adt::trans_field_ptr(
-            bcx, &*repr, adt::MaybeSizedValue::sized(dest_addr), 0, i);
+            bcx, &*repr, adt::MaybeSizedValue::sized(dest_addr), Disr(0), i);
         let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
                                      closure_expr_id: id };
         match tcx.upvar_capture(upvar_id).unwrap() {
@@ -254,7 +255,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
             }
         }
     }
-    adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
+    adt::trans_set_discr(bcx, &*repr, dest_addr, Disr(0));
 
     Some(bcx)
 }
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 5046c2e2920..1342accd388 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -161,6 +161,8 @@ pub fn gensym_name(name: &str) -> ast::Name {
 *
 */
 
+use trans::Disr;
+
 #[derive(Copy, Clone)]
 pub struct NodeIdAndSpan {
     pub id: ast::NodeId,
@@ -177,7 +179,7 @@ pub struct Field<'tcx>(pub ast::Name, pub Ty<'tcx>);
 
 /// The concrete version of ty::VariantDef
 pub struct VariantInfo<'tcx> {
-    pub discr: ty::Disr,
+    pub discr: Disr,
     pub fields: Vec<Field<'tcx>>
 }
 
@@ -195,7 +197,7 @@ impl<'tcx> VariantInfo<'tcx> {
                 };
 
                 VariantInfo {
-                    discr: variant.disr_val,
+                    discr: Disr::from(variant.disr_val),
                     fields: variant.fields.iter().map(|f| {
                         Field(f.name, monomorphize::field_ty(tcx, substs, f))
                     }).collect()
@@ -204,7 +206,7 @@ impl<'tcx> VariantInfo<'tcx> {
 
             ty::TyTuple(ref v) => {
                 VariantInfo {
-                    discr: 0,
+                    discr: Disr(0),
                     fields: v.iter().enumerate().map(|(i, &t)| {
                         Field(token::intern(&i.to_string()), t)
                     }).collect()
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index d5a7995b65d..0fc87970733 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -37,6 +37,7 @@ use trans::declare;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
+use trans::Disr;
 use middle::subst::Substs;
 use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
 use middle::ty::adjustment::AdjustUnsafeFnPointer;
@@ -740,7 +741,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 (CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => {
                     let repr = adt::represent_type(cx, t_expr);
                     let discr = adt::const_get_discrim(cx, &*repr, v);
-                    let iv = C_integral(cx.int_type(), discr, false);
+                    let iv = C_integral(cx.int_type(), discr.0, false);
                     let s = adt::is_discr_signed(&*repr) as Bool;
                     llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
                 },
@@ -807,7 +808,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir::ExprTup(ref es) => {
             let repr = adt::represent_type(cx, ety);
             let vals = try!(map_list(&es[..]));
-            adt::trans_const(cx, &*repr, 0, &vals[..])
+            adt::trans_const(cx, &*repr, Disr(0), &vals[..])
         },
         hir::ExprStruct(_, ref fs, ref base_opt) => {
             let repr = adt::represent_type(cx, ety);
@@ -898,7 +899,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     match vinfo.kind() {
                         ty::VariantKind::Unit => {
                             let repr = adt::represent_type(cx, ety);
-                            adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
+                            adt::trans_const(cx, &*repr, Disr::from(vinfo.disr_val), &[])
                         }
                         ty::VariantKind::Tuple => {
                             expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
@@ -952,7 +953,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         C_vector(&arg_vals[..])
                     } else {
                         let repr = adt::represent_type(cx, ety);
-                        adt::trans_const(cx, &*repr, 0, &arg_vals[..])
+                        adt::trans_const(cx, &*repr, Disr(0), &arg_vals[..])
                     }
                 }
                 def::DefVariant(enum_did, variant_did, _) => {
@@ -960,7 +961,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
                     adt::trans_const(cx,
                                      &*repr,
-                                     vinfo.disr_val,
+                                     Disr::from(vinfo.disr_val),
                                      &arg_vals[..])
                 }
                 _ => cx.sess().span_bug(e.span, "expected a struct, variant, or const fn def"),
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index d90acd78147..d967c728d16 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -1341,7 +1341,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                 // DWARF representation of enums uniform.
 
                 // First create a description of the artificial wrapper struct:
-                let non_null_variant = &adt.variants[non_null_variant_index as usize];
+                let non_null_variant = &adt.variants[non_null_variant_index.0 as usize];
                 let non_null_variant_name = non_null_variant.name.as_str();
 
                 // The llvm type and metadata of the pointer
@@ -1389,7 +1389,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
 
                 // Encode the information about the null variant in the union
                 // member's name.
-                let null_variant_index = (1 - non_null_variant_index) as usize;
+                let null_variant_index = (1 - non_null_variant_index.0) as usize;
                 let null_variant_name = adt.variants[null_variant_index].name;
                 let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
                                                 0,
@@ -1415,7 +1415,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                     describe_enum_variant(cx,
                                           self.enum_type,
                                           struct_def,
-                                          &adt.variants[nndiscr as usize],
+                                          &adt.variants[nndiscr.0 as usize],
                                           OptimizedDiscriminant,
                                           self.containing_scope,
                                           self.span);
@@ -1430,7 +1430,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
 
                 // Encode the information about the null variant in the union
                 // member's name.
-                let null_variant_index = (1 - nndiscr) as usize;
+                let null_variant_index = (1 - nndiscr.0) as usize;
                 let null_variant_name = adt.variants[null_variant_index].name;
                 let discrfield = discrfield.iter()
                                            .skip(1)
diff --git a/src/librustc_trans/trans/disr.rs b/src/librustc_trans/trans/disr.rs
new file mode 100644
index 00000000000..7cb10a8bc44
--- /dev/null
+++ b/src/librustc_trans/trans/disr.rs
@@ -0,0 +1,49 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub struct Disr(pub u64);
+
+impl Disr {
+    pub fn wrapping_add(self, other: Self) -> Self {
+        Disr(self.0.wrapping_add(other.0))
+    }
+}
+
+impl ::std::ops::BitAnd for Disr {
+    type Output = Disr;
+    fn bitand(self, other: Self) -> Self {
+        Disr(self.0 & other.0)
+    }
+}
+
+impl From<::middle::ty::Disr> for Disr {
+    fn from(i: ::middle::ty::Disr) -> Disr {
+        Disr(i)
+    }
+}
+
+impl From<usize> for Disr {
+    fn from(i: usize) -> Disr {
+        Disr(i as u64)
+    }
+}
+
+impl PartialOrd for Disr {
+    fn partial_cmp(&self, other: &Disr) -> Option<::std::cmp::Ordering> {
+        self.0.partial_cmp(&other.0)
+    }
+}
+
+impl Ord for Disr {
+    fn cmp(&self, other: &Disr) -> ::std::cmp::Ordering {
+        self.0.cmp(&other.0)
+    }
+}
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index f0ee518a0f5..ab2f4462757 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -71,6 +71,7 @@ use trans::machine;
 use trans::meth;
 use trans::tvec;
 use trans::type_of;
+use trans::Disr;
 use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
 use middle::ty::adjustment::{AdjustUnsafeFnPointer, CustomCoerceUnsized};
 use middle::ty::{self, Ty};
@@ -549,8 +550,8 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
             let iter = src_fields.iter().zip(target_fields).enumerate();
             for (i, (src_ty, target_ty)) in iter {
-                let ll_source = adt::trans_field_ptr(bcx, &repr_source, source_val, 0, i);
-                let ll_target = adt::trans_field_ptr(bcx, &repr_target, target_val, 0, i);
+                let ll_source = adt::trans_field_ptr(bcx, &repr_source, source_val, Disr(0), i);
+                let ll_target = adt::trans_field_ptr(bcx, &repr_target, target_val, Disr(0), i);
 
                 // If this is the field we need to coerce, recurse on it.
                 if i == coerce_index {
@@ -1154,7 +1155,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 args.iter().enumerate().map(|(i, arg)| (i, &**arg)).collect();
             trans_adt(bcx,
                       expr_ty(bcx, expr),
-                      0,
+                      Disr(0),
                       &numbered_fields[..],
                       None,
                       dest,
@@ -1295,7 +1296,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // Nullary variant.
                 let ty = expr_ty(bcx, ref_expr);
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                adt::trans_set_discr(bcx, &*repr, lldest, variant.disr_val);
+                adt::trans_set_discr(bcx, &*repr, lldest, Disr::from(variant.disr_val));
                 return bcx;
             }
         }
@@ -1304,7 +1305,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             match ty.sty {
                 ty::TyStruct(def, _) if def.has_dtor() => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
-                    adt::trans_set_discr(bcx, &*repr, lldest, 0);
+                    adt::trans_set_discr(bcx, &*repr, lldest, Disr(0));
                 }
                 _ => {}
             }
@@ -1466,7 +1467,7 @@ pub struct StructBaseInfo<'a, 'tcx> {
 /// which remaining fields are copied; see comments on `StructBaseInfo`.
 pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                  ty: Ty<'tcx>,
-                                 discr: ty::Disr,
+                                 discr: Disr,
                                  fields: &[(usize, &hir::Expr)],
                                  optbase: Option<StructBaseInfo<'a, 'tcx>>,
                                  dest: Dest,
@@ -1534,7 +1535,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         debug_location.apply(bcx.fcx);
 
         // Second, trans the base to the dest.
-        assert_eq!(discr, 0);
+        assert_eq!(discr, Disr(0));
 
         let addr = adt::MaybeSizedValue::sized(addr);
         match expr_kind(bcx.tcx(), &*base.expr) {
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 01fd36867ff..41c39a35987 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -27,6 +27,7 @@ use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
 use trans::type_of;
+use trans::Disr;
 use middle::infer;
 use middle::ty::{self, Ty};
 use middle::subst::Substs;
@@ -332,7 +333,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             llarg_rust
         } else {
             if passed_arg_tys[i].is_bool() {
-                let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, llvm::False);
+                let val = LoadRangeAssert(bcx, llarg_rust, Disr(0), Disr(2), llvm::False);
                 Trunc(bcx, val, Type::i1(bcx.ccx()))
             } else {
                 Load(bcx, llarg_rust)
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 07cc6ec8fbd..0c9b076cb65 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -36,6 +36,7 @@ use trans::type_of;
 use trans::machine;
 use trans::type_::Type;
 use middle::ty::{self, Ty, TypeFoldable};
+use trans::Disr;
 use middle::subst::Substs;
 use rustc::dep_graph::DepNode;
 use rustc_front::hir;
@@ -848,7 +849,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         let arg = adt::MaybeSizedValue::sized(llarg);
                         (0..contents.len())
                             .map(|i| {
-                                Load(bcx, adt::trans_field_ptr(bcx, repr_ptr, arg, 0, i))
+                                Load(bcx, adt::trans_field_ptr(bcx, repr_ptr, arg, Disr(0), i))
                             })
                             .collect()
                     }
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index ad5b0069a48..5446bbda4c2 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -18,6 +18,7 @@ use trans::common::{self, Block};
 use trans::debuginfo::DebugLoc;
 use trans::type_of;
 use trans::type_::Type;
+use trans::Disr;
 
 use super::MirContext;
 use super::operand::OperandValue::{FatPtr, Immediate, Ref};
@@ -60,7 +61,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let switch = build::Switch(bcx, discr, unreachable_blk.llbb, targets.len());
                 assert_eq!(adt_def.variants.len(), targets.len());
                 for (adt_variant, target) in adt_def.variants.iter().zip(targets) {
-                    let llval = adt::trans_case(bcx, &*repr, adt_variant.disr_val);
+                    let llval = adt::trans_case(bcx, &*repr, Disr::from(adt_variant.disr_val));
                     let llbb = self.llblock(*target);
 
                     build::AddCase(switch, llval, llbb)
diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs
index ba0427ec3d6..a6ba069742d 100644
--- a/src/librustc_trans/trans/mir/lvalue.rs
+++ b/src/librustc_trans/trans/mir/lvalue.rs
@@ -20,6 +20,7 @@ use trans::debuginfo::DebugLoc;
 use trans::machine;
 use trans::type_of;
 use llvm;
+use trans::Disr;
 
 use std::ptr;
 
@@ -137,7 +138,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         } else {
                             adt::MaybeSizedValue::unsized_(tr_base.llval, tr_base.llextra)
                         };
-                        (adt::trans_field_ptr(bcx, &base_repr, base, discr, field.index()),
+                        (adt::trans_field_ptr(bcx, &base_repr, base, Disr(discr), field.index()),
                          if is_sized {
                              ptr::null_mut()
                          } else {
diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs
index 7b9eac4317d..f53653d7cad 100644
--- a/src/librustc_trans/trans/mir/rvalue.rs
+++ b/src/librustc_trans/trans/mir/rvalue.rs
@@ -25,6 +25,7 @@ use trans::machine;
 use trans::type_::Type;
 use trans::type_of;
 use trans::tvec;
+use trans::Disr;
 
 use super::MirContext;
 use super::operand::{OperandRef, OperandValue};
@@ -100,8 +101,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 match *kind {
                     mir::AggregateKind::Adt(adt_def, index, _) => {
                         let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
-                        let disr = adt_def.variants[index].disr_val;
-                        adt::trans_set_discr(bcx, &*repr, dest.llval, disr);
+                        let disr = Disr::from(adt_def.variants[index].disr_val);
+                        adt::trans_set_discr(bcx, &*repr, dest.llval, Disr::from(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.
diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs
index f474e288efe..d87c17cbf88 100644
--- a/src/librustc_trans/trans/mod.rs
+++ b/src/librustc_trans/trans/mod.rs
@@ -14,6 +14,7 @@ use middle::cstore::LinkMeta;
 pub use self::base::trans_crate;
 pub use self::context::CrateContext;
 pub use self::common::gensym_name;
+pub use self::disr::Disr;
 
 #[macro_use]
 mod macros;
@@ -45,6 +46,7 @@ mod controlflow;
 mod datum;
 mod debuginfo;
 mod declare;
+mod disr;
 mod expr;
 mod foreign;
 mod glue;
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 416c1908c97..62e69cbb85e 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -24,6 +24,7 @@ use trans::common::*;
 use trans::declare;
 use trans::foreign;
 use middle::ty::{self, Ty};
+use trans::Disr;
 use rustc::front::map as hir_map;
 
 use rustc_front::hir;
@@ -207,7 +208,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             assert_eq!(v.node.name, variant.name);
             let d = mk_lldecl(abi::Rust);
             attributes::inline(d, attributes::InlineAttr::Hint);
-            trans_enum_variant(ccx, fn_node_id, variant.disr_val, psubsts, d);
+            trans_enum_variant(ccx, fn_node_id, Disr::from(variant.disr_val), psubsts, d);
             d
         }
         hir_map::NodeImplItem(impl_item) => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 0f87dc88852..d501641b538 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4178,7 +4178,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                     sp: Span,
                                     vs: &'tcx [hir::Variant],
                                     id: ast::NodeId) {
-
+    // disr_in_range should be removed once we have forced type hints for consts
     fn disr_in_range(ccx: &CrateCtxt,
                      ty: attr::IntType,
                      disr: ty::Disr) -> bool {