about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-08-05 16:11:24 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-09-11 08:41:15 +0300
commit8a9b78f5cca1a0585e52a19d79ea9503f5534345 (patch)
treeb6ad436a5c183c4577c8155d74e217e5735924e2
parent3ce31eb99076261291c1a0ae4b542f52e6ca0f0a (diff)
downloadrust-8a9b78f5cca1a0585e52a19d79ea9503f5534345.tar.gz
rust-8a9b78f5cca1a0585e52a19d79ea9503f5534345.zip
rustc: use ty::Const for the length of TyArray.
-rw-r--r--src/librustc/middle/const_val.rs17
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/mir/tcx.rs5
-rw-r--r--src/librustc/ty/context.rs12
-rw-r--r--src/librustc/ty/error.rs13
-rw-r--r--src/librustc/ty/flags.rs38
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs2
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/relate.rs10
-rw-r--r--src/librustc/ty/structural_impls.rs4
-rw-r--r--src/librustc/ty/sty.rs4
-rw-r--r--src/librustc/ty/util.rs4
-rw-r--r--src/librustc/ty/walk.rs43
-rw-r--r--src/librustc/ty/wf.rs13
-rw-r--r--src/librustc/util/ppaux.rs15
-rw-r--r--src/librustc_const_eval/_match.rs11
-rw-r--r--src/librustc_const_eval/eval.rs11
-rw-r--r--src/librustc_const_eval/pattern.rs3
-rw-r--r--src/librustc_mir/shim.rs5
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs3
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_trans/base.rs4
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs3
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs4
-rw-r--r--src/librustc_trans/mir/lvalue.rs4
-rw-r--r--src/librustc_trans/mir/rvalue.rs3
-rw-r--r--src/librustc_trans/trans_item.rs3
-rw-r--r--src/librustc_trans/type_of.rs3
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/check/_match.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs5
-rw-r--r--src/librustdoc/clean/mod.rs18
-rw-r--r--src/librustdoc/lib.rs1
34 files changed, 215 insertions, 60 deletions
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index d213bc1de20..05e4f0da001 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -247,18 +247,23 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
 }
 
 /// Returns the value of the length-valued expression
-pub fn eval_length(tcx: TyCtxt,
-                   count: hir::BodyId,
-                   reason: &str)
-                   -> Result<ConstUsize, ErrorReported>
+pub fn eval_length<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                   count: hir::BodyId,
+                                   reason: &str)
+                                   -> Result<&'gcx ty::Const<'gcx>, ErrorReported>
 {
     let count_expr = &tcx.hir.body(count).value;
     let count_def_id = tcx.hir.body_owner_def_id(count);
     let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
     let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
     match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
-        Ok(&ty::Const { val: Integral(Usize(count)), .. }) => Ok(count),
-        Ok(_) | Err(ConstEvalErr { kind: ErrKind::TypeckError, .. }) => Err(ErrorReported),
+        Ok(count) => {
+            // Elsewhere in the compiler this is enforced even in the presence
+            // of erroneous code (type mismatch error has already been emitted).
+            assert_eq!(count.ty, tcx.types.usize);
+            Ok(count)
+        }
+        Err(ConstEvalErr { kind: ErrKind::TypeckError, .. }) => Err(ErrorReported),
         Err(err) => {
             let mut diag = err.struct_error(tcx, count_expr.span, reason);
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 1a4d0dcd929..a270e0873c1 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -876,7 +876,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
-            ty::TyArray(_, len) if len.as_u64() == 0 => true,
+            ty::TyArray(_, len) if len.val.to_const_int().unwrap().to_u64().unwrap() == 0 => true,
             _ => promotable,
         };
 
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 7469402daf9..d645a00e157 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -70,7 +70,8 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
                 LvalueTy::Ty {
                     ty: match ty.sty {
                         ty::TyArray(inner, size) => {
-                            let len = size.as_u64() - (from as u64) - (to as u64);
+                            let size = size.val.to_const_int().unwrap().to_u64().unwrap();
+                            let len = size - (from as u64) - (to as u64);
                             tcx.mk_array(inner, len)
                         }
                         ty::TySlice(..) => ty,
@@ -148,7 +149,7 @@ impl<'tcx> Rvalue<'tcx> {
         match *self {
             Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
             Rvalue::Repeat(ref operand, count) => {
-                tcx.mk_array(operand.ty(local_decls, tcx), count.as_u64())
+                tcx.mk_array_const_usize(operand.ty(local_decls, tcx), count)
             }
             Rvalue::Ref(reg, bk, ref lv) => {
                 let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx);
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 7a671b5ebc6..e02493add31 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -21,6 +21,7 @@ use hir::map as hir_map;
 use hir::map::DefPathHash;
 use lint::{self, Lint};
 use ich::{self, StableHashingContext, NodeIdHashingMode};
+use middle::const_val::ConstVal;
 use middle::free_region::FreeRegionMap;
 use middle::lang_items;
 use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
@@ -49,7 +50,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 
 use arena::{TypedArena, DroplessArena};
-use rustc_const_math::ConstUsize;
+use rustc_const_math::{ConstInt, ConstUsize};
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
@@ -1757,7 +1758,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
         let n = ConstUsize::new(n, self.sess.target.usize_ty).unwrap();
-        self.mk_ty(TyArray(ty, n))
+        self.mk_array_const_usize(ty, n)
+    }
+
+    pub fn mk_array_const_usize(self, ty: Ty<'tcx>, n: ConstUsize) -> Ty<'tcx> {
+        self.mk_ty(TyArray(ty, self.mk_const(ty::Const {
+            val: ConstVal::Integral(ConstInt::Usize(n)),
+            ty: self.types.usize
+        })))
     }
 
     pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 3234a9de8c7..52a8389bd8f 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -10,6 +10,7 @@
 
 use hir::def_id::DefId;
 use infer::type_variable;
+use middle::const_val::ConstVal;
 use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
 
 use std::fmt;
@@ -18,7 +19,7 @@ use syntax::ast;
 use errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
-use rustc_const_math::ConstUsize;
+use rustc_const_math::ConstInt;
 
 use hir;
 
@@ -36,7 +37,7 @@ pub enum TypeError<'tcx> {
     AbiMismatch(ExpectedFound<abi::Abi>),
     Mutability,
     TupleSize(ExpectedFound<usize>),
-    FixedArraySize(ExpectedFound<ConstUsize>),
+    FixedArraySize(ExpectedFound<u64>),
     ArgCount,
 
     RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
@@ -181,7 +182,13 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
             ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
 
             ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
-            ty::TyArray(_, n) => format!("array of {} elements", n),
+            ty::TyArray(_, n) => {
+                if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
+                    format!("array of {} elements", n)
+                } else {
+                    "array".to_string()
+                }
+            }
             ty::TySlice(_) => "slice".to_string(),
             ty::TyRawPtr(_) => "*-ptr".to_string(),
             ty::TyRef(region, tymut) => {
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 27b8d245396..62e39a507f2 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::const_val::{ConstVal, ConstAggregate};
 use ty::subst::Substs;
 use ty::{self, Ty, TypeFlags, TypeFoldable};
 
@@ -145,7 +146,12 @@ impl FlagComputation {
                 self.add_region(r);
             }
 
-            &ty::TyArray(tt, _) | &ty::TySlice(tt) => {
+            &ty::TyArray(tt, len) => {
+                self.add_ty(tt);
+                self.add_const(len);
+            }
+
+            &ty::TySlice(tt) => {
                 self.add_ty(tt)
             }
 
@@ -202,6 +208,36 @@ impl FlagComputation {
         }
     }
 
+    fn add_const(&mut self, constant: &ty::Const) {
+        self.add_ty(constant.ty);
+        match constant.val {
+            ConstVal::Integral(_) |
+            ConstVal::Float(_) |
+            ConstVal::Str(_) |
+            ConstVal::ByteStr(_) |
+            ConstVal::Bool(_) |
+            ConstVal::Char(_) |
+            ConstVal::Variant(_) => {}
+            ConstVal::Function(_, substs) => {
+                self.add_substs(substs);
+            }
+            ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
+                for &(_, v) in fields {
+                    self.add_const(v);
+                }
+            }
+            ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
+            ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
+                for v in fields {
+                    self.add_const(v);
+                }
+            }
+            ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
+                self.add_const(v);
+            }
+        }
+    }
+
     fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) {
         self.add_substs(projection.substs);
         self.add_ty(projection.ty);
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index bb8ef28bbf5..e10a4fb9f93 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -205,7 +205,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                 }))
             },
             TyArray(ty, len) => {
-                if len.as_u64() == 0 {
+                if len.val.to_const_int().unwrap().to_u64().unwrap() == 0 {
                     DefIdForest::empty()
                 } else {
                     ty.uninhabited_from(visited, tcx)
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 4d94021d2c8..bb16413c17f 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -837,7 +837,7 @@ impl<'a, 'tcx> Struct {
 
             // Is this a fixed-size array of something non-zero
             // with at least one element?
-            (_, &ty::TyArray(ety, d)) if d.as_u64() > 0 => {
+            (_, &ty::TyArray(ety, d)) if d.val.to_const_int().unwrap().to_u64().unwrap() != 0 => {
                 Struct::non_zero_field_paths(
                     tcx,
                     param_env,
@@ -1177,7 +1177,7 @@ impl<'a, 'tcx> Layout {
             ty::TyArray(element, count) => {
                 let element = element.layout(tcx, param_env)?;
                 let element_size = element.size(dl);
-                let count = count.as_u64();
+                let count = count.val.to_const_int().unwrap().to_u64().unwrap();
                 if element_size.checked_mul(count, dl).is_none() {
                     return Err(LayoutError::SizeOverflow(ty));
                 }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 0acb8a2c1d1..eb465ed16a2 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -428,10 +428,14 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
         (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) =>
         {
             let t = relation.relate(&a_t, &b_t)?;
-            if sz_a == sz_b {
-                Ok(tcx.mk_array(t, sz_a.as_u64()))
+            assert_eq!(sz_a.ty, tcx.types.usize);
+            assert_eq!(sz_b.ty, tcx.types.usize);
+            let sz_a_u64 = sz_a.val.to_const_int().unwrap().to_u64().unwrap();
+            let sz_b_u64 = sz_b.val.to_const_int().unwrap().to_u64().unwrap();
+            if sz_a_u64 == sz_b_u64 {
+                Ok(tcx.mk_ty(ty::TyArray(t, sz_a)))
             } else {
-                Err(TypeError::FixedArraySize(expected_found(relation, &sz_a, &sz_b)))
+                Err(TypeError::FixedArraySize(expected_found(relation, &sz_a_u64, &sz_b_u64)))
             }
         }
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index f260e20a3cd..758edd7d0c3 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -552,7 +552,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let sty = match self.sty {
             ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)),
-            ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz),
+            ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz.fold_with(folder)),
             ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
             ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
             ty::TyDynamic(ref trait_ty, ref region) =>
@@ -590,7 +590,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match self.sty {
             ty::TyRawPtr(ref tm) => tm.visit_with(visitor),
-            ty::TyArray(typ, _sz) => typ.visit_with(visitor),
+            ty::TyArray(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor),
             ty::TySlice(typ) => typ.visit_with(visitor),
             ty::TyAdt(_, substs) => substs.visit_with(visitor),
             ty::TyDynamic(ref trait_ty, ref reg) =>
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index e01f9f24235..f17f81ca06b 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -27,8 +27,6 @@ use syntax::ast::{self, Name};
 use syntax::symbol::keywords;
 use util::nodemap::FxHashMap;
 
-use rustc_const_math::ConstUsize;
-
 use serialize;
 
 use hir;
@@ -112,7 +110,7 @@ pub enum TypeVariants<'tcx> {
     TyStr,
 
     /// An array with the given length. Written as `[T; n]`.
-    TyArray(Ty<'tcx>, ConstUsize),
+    TyArray(Ty<'tcx>, &'tcx ty::Const<'tcx>),
 
     /// The pointee of an array slice.  Written as `[T]`.
     TySlice(Ty<'tcx>),
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index de4481116d6..95618717e0e 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -697,7 +697,9 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
             TyInt(i) => self.hash(i),
             TyUint(u) => self.hash(u),
             TyFloat(f) => self.hash(f),
-            TyArray(_, n) => self.hash(n),
+            TyArray(_, n) => {
+                self.hash(n.val.to_const_int().unwrap().to_u64().unwrap())
+            }
             TyRawPtr(m) |
             TyRef(_, m) => self.hash(m.mutbl),
             TyClosure(def_id, _) |
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index bfabacdb172..4d7eb37ca26 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -11,6 +11,7 @@
 //! An iterator over the type substructure.
 //! WARNING: this does not keep track of the region depth.
 
+use middle::const_val::{ConstVal, ConstAggregate};
 use ty::{self, Ty};
 use rustc_data_structures::small_vec::SmallVec;
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
@@ -83,7 +84,11 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
         ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => {
         }
-        ty::TyArray(ty, _) | ty::TySlice(ty) => {
+        ty::TyArray(ty, len) => {
+            push_const(stack, len);
+            stack.push(ty);
+        }
+        ty::TySlice(ty) => {
             stack.push(ty);
         }
         ty::TyRawPtr(ref mt) | ty::TyRef(_, ref mt) => {
@@ -122,13 +127,39 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyFnDef(_, substs) => {
             stack.extend(substs.types().rev());
         }
-        ty::TyFnPtr(ft) => {
-            push_sig_subtypes(stack, ft);
+        ty::TyFnPtr(sig) => {
+            stack.push(sig.skip_binder().output());
+            stack.extend(sig.skip_binder().inputs().iter().cloned().rev());
         }
     }
 }
 
-fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: ty::PolyFnSig<'tcx>) {
-    stack.push(sig.skip_binder().output());
-    stack.extend(sig.skip_binder().inputs().iter().cloned().rev());
+fn push_const<'tcx>(stack: &mut TypeWalkerStack<'tcx>, constant: &'tcx ty::Const<'tcx>) {
+    match constant.val {
+        ConstVal::Integral(_) |
+        ConstVal::Float(_) |
+        ConstVal::Str(_) |
+        ConstVal::ByteStr(_) |
+        ConstVal::Bool(_) |
+        ConstVal::Char(_) |
+        ConstVal::Variant(_) => {}
+        ConstVal::Function(_, substs) => {
+            stack.extend(substs.types().rev());
+        }
+        ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
+            for &(_, v) in fields.iter().rev() {
+                push_const(stack, v);
+            }
+        }
+        ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
+        ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
+            for v in fields.iter().rev() {
+                push_const(stack, v);
+            }
+        }
+        ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
+            push_const(stack, v);
+        }
+    }
+    stack.push(constant.ty);
 }
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 3516f7dfb25..4d2b15b6bf0 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -207,6 +207,10 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
         }
     }
 
+    /// Pushes the obligations required for a constant value to be WF
+    /// into `self.out`.
+    fn compute_const(&mut self, _constant: &'tcx ty::Const<'tcx>) {}
+
     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
         if !subty.has_escaping_regions() {
             let cause = self.cause(cause);
@@ -239,9 +243,14 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                     // WfScalar, WfParameter, etc
                 }
 
-                ty::TySlice(subty) |
-                ty::TyArray(subty, _) => {
+                ty::TySlice(subty) => {
+                    self.require_sized(subty, traits::SliceOrArrayElem);
+                }
+
+                ty::TyArray(subty, len) => {
                     self.require_sized(subty, traits::SliceOrArrayElem);
+                    assert_eq!(len.ty, self.infcx.tcx.types.usize);
+                    self.compute_const(len);
                 }
 
                 ty::TyTuple(ref tys, _) => {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 9cc978a057b..6b74022806c 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -10,6 +10,7 @@
 
 use hir::def_id::DefId;
 use hir::map::definitions::DefPathData;
+use middle::const_val::ConstVal;
 use middle::region::{self, BlockRemainder};
 use ty::subst::{self, Subst};
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
@@ -24,6 +25,7 @@ use std::cell::Cell;
 use std::fmt;
 use std::usize;
 
+use rustc_const_math::ConstInt;
 use syntax::abi::Abi;
 use syntax::ast::CRATE_NODE_ID;
 use syntax::symbol::Symbol;
@@ -886,7 +888,18 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
 
                 write!(f, "]")
             }),
-            TyArray(ty, sz) => write!(f, "[{}; {}]",  ty, sz),
+            TyArray(ty, sz) => {
+                write!(f, "[{}; ", ty)?;
+                match sz.val {
+                    ConstVal::Integral(ConstInt::Usize(sz)) => {
+                        write!(f, "{}", sz)?;
+                    }
+                    _ => {
+                        write!(f, "{:?}", sz)?;
+                    }
+                }
+                write!(f, "]")
+            }
             TySlice(ty) => write!(f, "[{}]",  ty)
         }
     }
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index 429332873c0..efe6cfb5464 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -422,11 +422,12 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
             }
         }
-        ty::TyArray(ref sub_ty, length) => {
-            if length.as_u64() > 0 && cx.is_uninhabited(sub_ty) {
+        ty::TyArray(ref sub_ty, len) => {
+            let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+            if len != 0 && cx.is_uninhabited(sub_ty) {
                 vec![]
             } else {
-                vec![Slice(length.as_u64())]
+                vec![Slice(len)]
             }
         }
         ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
@@ -729,7 +730,9 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
         PatternKind::Range { lo, hi, end } =>
             Some(vec![ConstantRange(lo, hi, end)]),
         PatternKind::Array { .. } => match pcx.ty.sty {
-            ty::TyArray(_, length) => Some(vec![Slice(length.as_u64())]),
+            ty::TyArray(_, length) => Some(vec![
+                Slice(length.val.to_const_int().unwrap().to_u64().unwrap())
+            ]),
             _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
         },
         PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 9dab067f942..1e3d1181281 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -456,7 +456,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
       }
       hir::ExprRepeat(ref elem, _) => {
           let n = match ty.sty {
-            ty::TyArray(_, n) => n.as_u64(),
+            ty::TyArray(_, n) => n.val.to_const_int().unwrap().to_u64().unwrap(),
             _ => span_bug!(e.span, "typeck error")
           };
           mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
@@ -635,8 +635,13 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr"))
             },
             ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
-                ty::TyArray(ty, n) if ty == tcx.types.u8 && n.as_u64() == b.data.len() as u64 => {
-                    Ok(val)
+                ty::TyArray(ty, n) => {
+                    let n = n.val.to_const_int().unwrap().to_u64().unwrap();
+                    if ty == tcx.types.u8 && n == b.data.len() as u64 {
+                        Ok(val)
+                    } else {
+                        Err(CannotCast)
+                    }
                 }
                 ty::TySlice(_) => {
                     Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice"))
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index 6274796145e..0a2e78dd51a 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -537,7 +537,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
             ty::TyArray(_, len) => {
                 // fixed-length array
-                assert!(len.as_u64() >= prefix.len() as u64 + suffix.len() as u64);
+                let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+                assert!(len >= prefix.len() as u64 + suffix.len() as u64);
                 PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
             }
 
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index eddd4f39f43..00ee417e02b 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -292,7 +292,10 @@ fn build_clone_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 
     match self_ty.sty {
         _ if is_copy => builder.copy_shim(),
-        ty::TyArray(ty, len) => builder.array_shim(ty, len.as_u64()),
+        ty::TyArray(ty, len) => {
+            let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+            builder.array_shim(ty, len)
+        }
         ty::TyTuple(tys, _) => builder.tuple_shim(tys),
         _ => {
             bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty);
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 30074becb09..2267e611531 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -696,7 +696,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                             _ => false
                         }
                     } else if let ty::TyArray(_, len) = ty.sty {
-                        len.as_u64() == 0 && self.mode == Mode::Fn
+                        len.val.to_const_int().unwrap().to_u64().unwrap() == 0 &&
+                            self.mode == Mode::Fn
                     } else {
                         false
                     };
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 07134451a4e..ab5998a3480 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -209,7 +209,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 LvalueTy::Ty {
                     ty: match base_ty.sty {
                         ty::TyArray(inner, size) => {
-                            let size = size.as_u64();
+                            let size = size.val.to_const_int().unwrap().to_u64().unwrap();
                             let min_size = (from as u64) + (to as u64);
                             if let Some(rest_size) = size.checked_sub(min_size) {
                                 tcx.mk_array(inner, rest_size)
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 96499424be1..73209affe99 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -201,7 +201,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
                                 -> ValueRef {
     let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
-        (&ty::TyArray(_, len), &ty::TySlice(_)) => C_usize(ccx, len.as_u64()),
+        (&ty::TyArray(_, len), &ty::TySlice(_)) => {
+            C_usize(ccx, len.val.to_const_int().unwrap().to_u64().unwrap())
+        }
         (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
             // For now, upcasts are limited to changes in marker
             // traits, and hence never actually require an actual
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 0ef93e73c4b..3c87bc293b5 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -530,7 +530,8 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
         ty::TyArray(typ, len) => {
-            fixed_vec_metadata(cx, unique_type_id, typ, Some(len.as_u64()), usage_site_span)
+            let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+            fixed_vec_metadata(cx, unique_type_id, typ, Some(len), usage_site_span)
         }
         ty::TySlice(typ) => {
             fixed_vec_metadata(cx, unique_type_id, typ, None, usage_site_span)
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 6eda8657519..7bf9d39ea2f 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -96,7 +96,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyArray(inner_type, len) => {
             output.push('[');
             push_debuginfo_type_name(cx, inner_type, true, output);
-            output.push_str(&format!("; {}", len));
+            output.push_str(&format!("; {}", len.val.to_const_int().unwrap().to_u64().unwrap()));
             output.push(']');
         },
         ty::TySlice(inner_type) => {
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index f75c949fefe..072d351dd61 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -200,7 +200,9 @@ impl<'tcx> ConstLvalue<'tcx> {
 
     pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
         match self.ty.sty {
-            ty::TyArray(_, n) => C_usize(ccx, n.as_u64()),
+            ty::TyArray(_, n) => {
+                C_usize(ccx, n.val.to_const_int().unwrap().to_u64().unwrap())
+            }
             ty::TySlice(_) | ty::TyStr => {
                 assert!(self.llextra != ptr::null_mut());
                 self.llextra
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index d34885a1e93..6799e52904d 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -106,7 +106,9 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
     pub fn len(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
         let ty = self.ty.to_ty(ccx.tcx());
         match ty.sty {
-            ty::TyArray(_, n) => common::C_usize(ccx, n.as_u64()),
+            ty::TyArray(_, n) => {
+                common::C_usize(ccx, n.val.to_const_int().unwrap().to_u64().unwrap())
+            }
             ty::TySlice(_) | ty::TyStr => {
                 assert!(self.llextra != ptr::null_mut());
                 self.llextra
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 0f2d0c7f296..20ed4ab50a0 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -521,7 +521,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if common::type_is_zero_size(bcx.ccx, op.ty) {
                     if let ty::TyArray(_, n) = op.ty.sty {
-                        return common::C_usize(bcx.ccx, n.as_u64());
+                        let n = n.val.to_const_int().unwrap().to_u64().unwrap();
+                        return common::C_usize(bcx.ccx, n);
                     }
                 }
             }
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 672fa32aa85..1f27eb9fcb3 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -446,7 +446,8 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
             ty::TyArray(inner_type, len) => {
                 output.push('[');
                 self.push_type_name(inner_type, output);
-                write!(output, "; {}", len).unwrap();
+                write!(output, "; {}",
+                    len.val.to_const_int().unwrap().to_u64().unwrap()).unwrap();
                 output.push(']');
             },
             ty::TySlice(inner_type) => {
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index 149a55f8c05..992c74b9020 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -149,7 +149,8 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
 
       ty::TyArray(ty, size) => {
           let llty = in_memory_type_of(cx, ty);
-          Type::array(&llty, size.as_u64())
+          let size = size.val.to_const_int().unwrap().to_u64().unwrap();
+          Type::array(&llty, size)
       }
 
       // Unsized slice types (and str) have the type of their element, and
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index fc05ce4cd66..6759b6a422d 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1083,7 +1083,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
             hir::TyArray(ref ty, length) => {
                 if let Ok(length) = eval_length(tcx, length, "array length") {
-                    tcx.mk_array(self.ast_ty_to_ty(&ty), length.as_u64())
+                    tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length))
                 } else {
                     self.tcx().types.err
                 }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 02017652a6c..cbf58209d05 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -264,7 +264,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 let (inner_ty, slice_ty) = match expected_ty.sty {
                     ty::TyArray(inner_ty, size) => {
-                        let size = size.as_u64();
+                        let size = size.val.to_const_int().unwrap().to_u64().unwrap();
                         let min_len = before.len() as u64 + after.len() as u64;
                         if slice.is_none() {
                             if min_len != size {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 0adfca6e886..0ed3cc1e905 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3923,7 +3923,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             };
 
             if let Ok(count) = count {
-                if count.as_u64() > 1 {
+                let zero_or_one = count.val.to_const_int().and_then(|count| {
+                    count.to_u64().map(|count| count <= 1)
+                }).unwrap_or(false);
+                if !zero_or_one {
                     // For [foo, ..n] where n > 1, `foo` must have
                     // Copy type:
                     let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a78f15dd283..69c05050dac 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -27,6 +27,7 @@ use syntax::ptr::P;
 use syntax::symbol::keywords;
 use syntax_pos::{self, DUMMY_SP, Pos};
 
+use rustc::middle::const_val::ConstVal;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::resolve_lifetime as rl;
 use rustc::middle::lang_items;
@@ -40,6 +41,7 @@ use rustc_typeck::hir_ty_to_ty;
 
 use rustc::hir;
 
+use rustc_const_math::ConstInt;
 use std::{mem, slice, vec};
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -1785,7 +1787,12 @@ impl Clean<Type> for hir::Ty {
             TyArray(ref ty, length) => {
                 use rustc::middle::const_val::eval_length;
                 let n = eval_length(cx.tcx, length, "array length").unwrap();
-                Array(box ty.clean(cx), n.to_string())
+                let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
+                    n.to_string()
+                } else {
+                    format!("{:?}", n)
+                };
+                Array(box ty.clean(cx), n)
             },
             TyTup(ref tys) => Tuple(tys.clean(cx)),
             TyPath(hir::QPath::Resolved(None, ref path)) => {
@@ -1895,7 +1902,14 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
             ty::TyFloat(float_ty) => Primitive(float_ty.into()),
             ty::TyStr => Primitive(PrimitiveType::Str),
             ty::TySlice(ty) => Slice(box ty.clean(cx)),
-            ty::TyArray(ty, n) => Array(box ty.clean(cx), n.to_string()),
+            ty::TyArray(ty, n) => {
+                let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
+                    n.to_string()
+                } else {
+                    format!("{:?}", n)
+                };
+                Array(box ty.clean(cx), n)
+            }
             ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
             ty::TyRef(r, mt) => BorrowedRef {
                 lifetime: r.clean(cx),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d04b6d3417a..9563ccfcc65 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -32,6 +32,7 @@ extern crate html_diff;
 extern crate libc;
 extern crate rustc;
 extern crate rustc_data_structures;
+extern crate rustc_const_math;
 extern crate rustc_trans;
 extern crate rustc_driver;
 extern crate rustc_resolve;