From 8a9b78f5cca1a0585e52a19d79ea9503f5534345 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 5 Aug 2017 16:11:24 +0300 Subject: [PATCH] rustc: use ty::Const for the length of TyArray. --- src/librustc/middle/const_val.rs | 17 +++++--- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/mir/tcx.rs | 5 ++- src/librustc/ty/context.rs | 12 +++++- src/librustc/ty/error.rs | 13 ++++-- src/librustc/ty/flags.rs | 38 ++++++++++++++++- src/librustc/ty/inhabitedness/mod.rs | 2 +- src/librustc/ty/layout.rs | 4 +- src/librustc/ty/relate.rs | 10 +++-- src/librustc/ty/structural_impls.rs | 4 +- src/librustc/ty/sty.rs | 4 +- src/librustc/ty/util.rs | 4 +- src/librustc/ty/walk.rs | 43 +++++++++++++++++--- src/librustc/ty/wf.rs | 13 +++++- src/librustc/util/ppaux.rs | 15 ++++++- src/librustc_const_eval/_match.rs | 11 +++-- src/librustc_const_eval/eval.rs | 11 +++-- src/librustc_const_eval/pattern.rs | 3 +- src/librustc_mir/shim.rs | 5 ++- src/librustc_mir/transform/qualify_consts.rs | 3 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_trans/base.rs | 4 +- src/librustc_trans/debuginfo/metadata.rs | 3 +- src/librustc_trans/debuginfo/type_names.rs | 2 +- src/librustc_trans/mir/constant.rs | 4 +- src/librustc_trans/mir/lvalue.rs | 4 +- src/librustc_trans/mir/rvalue.rs | 3 +- src/librustc_trans/trans_item.rs | 3 +- src/librustc_trans/type_of.rs | 3 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/mod.rs | 5 ++- src/librustdoc/clean/mod.rs | 18 +++++++- src/librustdoc/lib.rs | 1 + 34 files changed, 215 insertions(+), 60 deletions(-) diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index d213bc1de20a5..05e4f0da001cf 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 +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 1a4d0dcd929c3..a270e0873c1dd 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 7469402daf90f..d645a00e15781 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 7a671b5ebc6e0..e02493add31fb 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 3234a9de8c791..52a8389bd8f5f 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), Mutability, TupleSize(ExpectedFound), - FixedArraySize(ExpectedFound), + FixedArraySize(ExpectedFound), 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 27b8d245396c9..62e39a507f2bd 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 bb8ef28bbf593..e10a4fb9f9308 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 4d94021d2c8c5..bb16413c17fae 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 0acb8a2c1d159..eb465ed16a264 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 f260e20a3cd6c..758edd7d0c3bc 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>(&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 e01f9f24235c5..f17f81ca06bea 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 de4481116d6e1..95618717e0ea3 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 bfabacdb17214..4d7eb37ca26ed 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 3516f7dfb25b0..4d2b15b6bf069 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 9cc978a057bf6..6b74022806cf5 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 429332873c05b..efe6cfb5464ef 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 9dab067f942e8..1e3d118128163 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 6274796145e1f..0a2e78dd51a35 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 eddd4f39f4333..00ee417e02b55 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 30074becb09c7..2267e611531f3 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 07134451a4e29..ab5998a34805b 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 96499424be1f6..73209affe994b 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 0ef93e73c4bc8..3c87bc293b5b5 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 6eda865751933..7bf9d39ea2f25 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 f75c949fefe3a..072d351dd617a 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 d34885a1e9326..6799e52904d34 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 0f2d0c7f29617..20ed4ab50a00f 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 672fa32aa8591..1f27eb9fcb309 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 149a55f8c05d5..992c74b9020c3 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 fc05ce4cd662c..6759b6a422d09 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 02017652a6c71..cbf58209d056a 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 0adfca6e886a7..0ed3cc1e905cb 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 a78f15dd283c3..69c05050dacc9 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 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 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 d04b6d3417a5a..9563ccfcc65fd 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;