rustc: use ty::Const for the length of TyArray.

This commit is contained in:
Eduard-Mihai Burtescu 2017-08-05 16:11:24 +03:00
parent 3ce31eb990
commit 8a9b78f5cc
34 changed files with 215 additions and 60 deletions

View file

@ -247,18 +247,23 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
} }
/// Returns the value of the length-valued expression /// Returns the value of the length-valued expression
pub fn eval_length(tcx: TyCtxt, pub fn eval_length<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
count: hir::BodyId, count: hir::BodyId,
reason: &str) reason: &str)
-> Result<ConstUsize, ErrorReported> -> Result<&'gcx ty::Const<'gcx>, ErrorReported>
{ {
let count_expr = &tcx.hir.body(count).value; let count_expr = &tcx.hir.body(count).value;
let count_def_id = tcx.hir.body_owner_def_id(count); let count_def_id = tcx.hir.body_owner_def_id(count);
let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); 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))) { 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(count) => {
Ok(_) | Err(ConstEvalErr { kind: ErrKind::TypeckError, .. }) => Err(ErrorReported), // 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) => { Err(err) => {
let mut diag = err.struct_error(tcx, count_expr.span, reason); let mut diag = err.struct_error(tcx, count_expr.span, reason);

View file

@ -876,7 +876,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// Always promote `[T; 0]` (even when e.g. borrowed mutably). // Always promote `[T; 0]` (even when e.g. borrowed mutably).
let promotable = match expr_ty.sty { 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, _ => promotable,
}; };

View file

@ -70,7 +70,8 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
LvalueTy::Ty { LvalueTy::Ty {
ty: match ty.sty { ty: match ty.sty {
ty::TyArray(inner, size) => { 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) tcx.mk_array(inner, len)
} }
ty::TySlice(..) => ty, ty::TySlice(..) => ty,
@ -148,7 +149,7 @@ impl<'tcx> Rvalue<'tcx> {
match *self { match *self {
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
Rvalue::Repeat(ref operand, count) => { 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) => { Rvalue::Ref(reg, bk, ref lv) => {
let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx); let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx);

View file

@ -21,6 +21,7 @@ use hir::map as hir_map;
use hir::map::DefPathHash; use hir::map::DefPathHash;
use lint::{self, Lint}; use lint::{self, Lint};
use ich::{self, StableHashingContext, NodeIdHashingMode}; use ich::{self, StableHashingContext, NodeIdHashingMode};
use middle::const_val::ConstVal;
use middle::free_region::FreeRegionMap; use middle::free_region::FreeRegionMap;
use middle::lang_items; use middle::lang_items;
use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
@ -49,7 +50,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult}; StableHasherResult};
use arena::{TypedArena, DroplessArena}; use arena::{TypedArena, DroplessArena};
use rustc_const_math::ConstUsize; use rustc_const_math::{ConstInt, ConstUsize};
use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::indexed_vec::IndexVec;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cell::{Cell, RefCell}; 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> { pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
let n = ConstUsize::new(n, self.sess.target.usize_ty).unwrap(); 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> { pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {

View file

@ -10,6 +10,7 @@
use hir::def_id::DefId; use hir::def_id::DefId;
use infer::type_variable; use infer::type_variable;
use middle::const_val::ConstVal;
use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt}; use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
use std::fmt; use std::fmt;
@ -18,7 +19,7 @@ use syntax::ast;
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
use syntax_pos::Span; use syntax_pos::Span;
use rustc_const_math::ConstUsize; use rustc_const_math::ConstInt;
use hir; use hir;
@ -36,7 +37,7 @@ pub enum TypeError<'tcx> {
AbiMismatch(ExpectedFound<abi::Abi>), AbiMismatch(ExpectedFound<abi::Abi>),
Mutability, Mutability,
TupleSize(ExpectedFound<usize>), TupleSize(ExpectedFound<usize>),
FixedArraySize(ExpectedFound<ConstUsize>), FixedArraySize(ExpectedFound<u64>),
ArgCount, ArgCount,
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), 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::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), 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::TySlice(_) => "slice".to_string(),
ty::TyRawPtr(_) => "*-ptr".to_string(), ty::TyRawPtr(_) => "*-ptr".to_string(),
ty::TyRef(region, tymut) => { ty::TyRef(region, tymut) => {

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use middle::const_val::{ConstVal, ConstAggregate};
use ty::subst::Substs; use ty::subst::Substs;
use ty::{self, Ty, TypeFlags, TypeFoldable}; use ty::{self, Ty, TypeFlags, TypeFoldable};
@ -145,7 +146,12 @@ impl FlagComputation {
self.add_region(r); 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) 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) { fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) {
self.add_substs(projection.substs); self.add_substs(projection.substs);
self.add_ty(projection.ty); self.add_ty(projection.ty);

View file

@ -205,7 +205,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
})) }))
}, },
TyArray(ty, len) => { TyArray(ty, len) => {
if len.as_u64() == 0 { if len.val.to_const_int().unwrap().to_u64().unwrap() == 0 {
DefIdForest::empty() DefIdForest::empty()
} else { } else {
ty.uninhabited_from(visited, tcx) ty.uninhabited_from(visited, tcx)

View file

@ -837,7 +837,7 @@ impl<'a, 'tcx> Struct {
// Is this a fixed-size array of something non-zero // Is this a fixed-size array of something non-zero
// with at least one element? // 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( Struct::non_zero_field_paths(
tcx, tcx,
param_env, param_env,
@ -1177,7 +1177,7 @@ impl<'a, 'tcx> Layout {
ty::TyArray(element, count) => { ty::TyArray(element, count) => {
let element = element.layout(tcx, param_env)?; let element = element.layout(tcx, param_env)?;
let element_size = element.size(dl); 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() { if element_size.checked_mul(count, dl).is_none() {
return Err(LayoutError::SizeOverflow(ty)); return Err(LayoutError::SizeOverflow(ty));
} }

View file

@ -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)) => (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) =>
{ {
let t = relation.relate(&a_t, &b_t)?; let t = relation.relate(&a_t, &b_t)?;
if sz_a == sz_b { assert_eq!(sz_a.ty, tcx.types.usize);
Ok(tcx.mk_array(t, sz_a.as_u64())) 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 { } else {
Err(TypeError::FixedArraySize(expected_found(relation, &sz_a, &sz_b))) Err(TypeError::FixedArraySize(expected_found(relation, &sz_a_u64, &sz_b_u64)))
} }
} }

View file

@ -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 { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
let sty = match self.sty { let sty = match self.sty {
ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)), 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::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)), ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
ty::TyDynamic(ref trait_ty, ref region) => 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 { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match self.sty { match self.sty {
ty::TyRawPtr(ref tm) => tm.visit_with(visitor), 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::TySlice(typ) => typ.visit_with(visitor),
ty::TyAdt(_, substs) => substs.visit_with(visitor), ty::TyAdt(_, substs) => substs.visit_with(visitor),
ty::TyDynamic(ref trait_ty, ref reg) => ty::TyDynamic(ref trait_ty, ref reg) =>

View file

@ -27,8 +27,6 @@ use syntax::ast::{self, Name};
use syntax::symbol::keywords; use syntax::symbol::keywords;
use util::nodemap::FxHashMap; use util::nodemap::FxHashMap;
use rustc_const_math::ConstUsize;
use serialize; use serialize;
use hir; use hir;
@ -112,7 +110,7 @@ pub enum TypeVariants<'tcx> {
TyStr, TyStr,
/// An array with the given length. Written as `[T; n]`. /// 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]`. /// The pointee of an array slice. Written as `[T]`.
TySlice(Ty<'tcx>), TySlice(Ty<'tcx>),

View file

@ -697,7 +697,9 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
TyInt(i) => self.hash(i), TyInt(i) => self.hash(i),
TyUint(u) => self.hash(u), TyUint(u) => self.hash(u),
TyFloat(f) => self.hash(f), 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) | TyRawPtr(m) |
TyRef(_, m) => self.hash(m.mutbl), TyRef(_, m) => self.hash(m.mutbl),
TyClosure(def_id, _) | TyClosure(def_id, _) |

View file

@ -11,6 +11,7 @@
//! An iterator over the type substructure. //! An iterator over the type substructure.
//! WARNING: this does not keep track of the region depth. //! WARNING: this does not keep track of the region depth.
use middle::const_val::{ConstVal, ConstAggregate};
use ty::{self, Ty}; use ty::{self, Ty};
use rustc_data_structures::small_vec::SmallVec; use rustc_data_structures::small_vec::SmallVec;
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; 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::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => { 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); stack.push(ty);
} }
ty::TyRawPtr(ref mt) | ty::TyRef(_, ref mt) => { 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) => { ty::TyFnDef(_, substs) => {
stack.extend(substs.types().rev()); stack.extend(substs.types().rev());
} }
ty::TyFnPtr(ft) => { ty::TyFnPtr(sig) => {
push_sig_subtypes(stack, ft); 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>) { fn push_const<'tcx>(stack: &mut TypeWalkerStack<'tcx>, constant: &'tcx ty::Const<'tcx>) {
stack.push(sig.skip_binder().output()); match constant.val {
stack.extend(sig.skip_binder().inputs().iter().cloned().rev()); 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);
} }

View file

@ -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>) { fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
if !subty.has_escaping_regions() { if !subty.has_escaping_regions() {
let cause = self.cause(cause); let cause = self.cause(cause);
@ -239,11 +243,16 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
// WfScalar, WfParameter, etc // WfScalar, WfParameter, etc
} }
ty::TySlice(subty) | ty::TySlice(subty) => {
ty::TyArray(subty, _) => {
self.require_sized(subty, traits::SliceOrArrayElem); 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, _) => { ty::TyTuple(ref tys, _) => {
if let Some((_last, rest)) = tys.split_last() { if let Some((_last, rest)) = tys.split_last() {
for elem in rest { for elem in rest {

View file

@ -10,6 +10,7 @@
use hir::def_id::DefId; use hir::def_id::DefId;
use hir::map::definitions::DefPathData; use hir::map::definitions::DefPathData;
use middle::const_val::ConstVal;
use middle::region::{self, BlockRemainder}; use middle::region::{self, BlockRemainder};
use ty::subst::{self, Subst}; use ty::subst::{self, Subst};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
@ -24,6 +25,7 @@ use std::cell::Cell;
use std::fmt; use std::fmt;
use std::usize; use std::usize;
use rustc_const_math::ConstInt;
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::CRATE_NODE_ID; use syntax::ast::CRATE_NODE_ID;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
@ -886,7 +888,18 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
write!(f, "]") 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) TySlice(ty) => write!(f, "[{}]", ty)
} }
} }

View file

@ -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() (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
} }
} }
ty::TyArray(ref sub_ty, length) => { ty::TyArray(ref sub_ty, len) => {
if length.as_u64() > 0 && cx.is_uninhabited(sub_ty) { let len = len.val.to_const_int().unwrap().to_u64().unwrap();
if len != 0 && cx.is_uninhabited(sub_ty) {
vec![] vec![]
} else { } else {
vec![Slice(length.as_u64())] vec![Slice(len)]
} }
} }
ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => { 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 } => PatternKind::Range { lo, hi, end } =>
Some(vec![ConstantRange(lo, hi, end)]), Some(vec![ConstantRange(lo, hi, end)]),
PatternKind::Array { .. } => match pcx.ty.sty { 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) _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
}, },
PatternKind::Slice { ref prefix, ref slice, ref suffix } => { PatternKind::Slice { ref prefix, ref slice, ref suffix } => {

View file

@ -456,7 +456,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
} }
hir::ExprRepeat(ref elem, _) => { hir::ExprRepeat(ref elem, _) => {
let n = match ty.sty { 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") _ => span_bug!(e.span, "typeck error")
}; };
mk_const(Aggregate(Repeat(cx.eval(elem)?, n))) 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")) Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr"))
}, },
ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty { 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 => { ty::TyArray(ty, n) => {
Ok(val) 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(_) => { ty::TySlice(_) => {
Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice")) Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice"))

View file

@ -537,7 +537,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
ty::TyArray(_, len) => { ty::TyArray(_, len) => {
// fixed-length array // 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 } PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
} }

View file

@ -292,7 +292,10 @@ fn build_clone_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
match self_ty.sty { match self_ty.sty {
_ if is_copy => builder.copy_shim(), _ 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), ty::TyTuple(tys, _) => builder.tuple_shim(tys),
_ => { _ => {
bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty); bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty);

View file

@ -696,7 +696,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
_ => false _ => false
} }
} else if let ty::TyArray(_, len) = ty.sty { } 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 { } else {
false false
}; };

View file

@ -209,7 +209,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
LvalueTy::Ty { LvalueTy::Ty {
ty: match base_ty.sty { ty: match base_ty.sty {
ty::TyArray(inner, size) => { 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); let min_size = (from as u64) + (to as u64);
if let Some(rest_size) = size.checked_sub(min_size) { if let Some(rest_size) = size.checked_sub(min_size) {
tcx.mk_array(inner, rest_size) tcx.mk_array(inner, rest_size)

View file

@ -201,7 +201,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
-> ValueRef { -> ValueRef {
let (source, target) = ccx.tcx().struct_lockstep_tails(source, target); let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
match (&source.sty, &target.sty) { 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(..)) => { (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
// For now, upcasts are limited to changes in marker // For now, upcasts are limited to changes in marker
// traits, and hence never actually require an actual // traits, and hence never actually require an actual

View file

@ -530,7 +530,8 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
MetadataCreationResult::new(basic_type_metadata(cx, t), false) MetadataCreationResult::new(basic_type_metadata(cx, t), false)
} }
ty::TyArray(typ, len) => { 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) => { ty::TySlice(typ) => {
fixed_vec_metadata(cx, unique_type_id, typ, None, usage_site_span) fixed_vec_metadata(cx, unique_type_id, typ, None, usage_site_span)

View file

@ -96,7 +96,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyArray(inner_type, len) => { ty::TyArray(inner_type, len) => {
output.push('['); output.push('[');
push_debuginfo_type_name(cx, inner_type, true, output); 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(']'); output.push(']');
}, },
ty::TySlice(inner_type) => { ty::TySlice(inner_type) => {

View file

@ -200,7 +200,9 @@ impl<'tcx> ConstLvalue<'tcx> {
pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef { pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
match self.ty.sty { 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 => { ty::TySlice(_) | ty::TyStr => {
assert!(self.llextra != ptr::null_mut()); assert!(self.llextra != ptr::null_mut());
self.llextra self.llextra

View file

@ -106,7 +106,9 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
pub fn len(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef { pub fn len(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
let ty = self.ty.to_ty(ccx.tcx()); let ty = self.ty.to_ty(ccx.tcx());
match ty.sty { 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 => { ty::TySlice(_) | ty::TyStr => {
assert!(self.llextra != ptr::null_mut()); assert!(self.llextra != ptr::null_mut());
self.llextra self.llextra

View file

@ -521,7 +521,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
if let LocalRef::Operand(Some(op)) = self.locals[index] { if let LocalRef::Operand(Some(op)) = self.locals[index] {
if common::type_is_zero_size(bcx.ccx, op.ty) { if common::type_is_zero_size(bcx.ccx, op.ty) {
if let ty::TyArray(_, n) = op.ty.sty { 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);
} }
} }
} }

View file

@ -446,7 +446,8 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
ty::TyArray(inner_type, len) => { ty::TyArray(inner_type, len) => {
output.push('['); output.push('[');
self.push_type_name(inner_type, output); 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(']'); output.push(']');
}, },
ty::TySlice(inner_type) => { ty::TySlice(inner_type) => {

View file

@ -149,7 +149,8 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
ty::TyArray(ty, size) => { ty::TyArray(ty, size) => {
let llty = in_memory_type_of(cx, ty); 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 // Unsized slice types (and str) have the type of their element, and

View file

@ -1083,7 +1083,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
} }
hir::TyArray(ref ty, length) => { hir::TyArray(ref ty, length) => {
if let Ok(length) = eval_length(tcx, length, "array 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 { } else {
self.tcx().types.err self.tcx().types.err
} }

View file

@ -264,7 +264,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expected_ty = self.structurally_resolved_type(pat.span, expected); let expected_ty = self.structurally_resolved_type(pat.span, expected);
let (inner_ty, slice_ty) = match expected_ty.sty { let (inner_ty, slice_ty) = match expected_ty.sty {
ty::TyArray(inner_ty, size) => { 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; let min_len = before.len() as u64 + after.len() as u64;
if slice.is_none() { if slice.is_none() {
if min_len != size { if min_len != size {

View file

@ -3923,7 +3923,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}; };
if let Ok(count) = count { 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 // For [foo, ..n] where n > 1, `foo` must have
// Copy type: // Copy type:
let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);

View file

@ -27,6 +27,7 @@ use syntax::ptr::P;
use syntax::symbol::keywords; use syntax::symbol::keywords;
use syntax_pos::{self, DUMMY_SP, Pos}; use syntax_pos::{self, DUMMY_SP, Pos};
use rustc::middle::const_val::ConstVal;
use rustc::middle::privacy::AccessLevels; use rustc::middle::privacy::AccessLevels;
use rustc::middle::resolve_lifetime as rl; use rustc::middle::resolve_lifetime as rl;
use rustc::middle::lang_items; use rustc::middle::lang_items;
@ -40,6 +41,7 @@ use rustc_typeck::hir_ty_to_ty;
use rustc::hir; use rustc::hir;
use rustc_const_math::ConstInt;
use std::{mem, slice, vec}; use std::{mem, slice, vec};
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
@ -1785,7 +1787,12 @@ impl Clean<Type> for hir::Ty {
TyArray(ref ty, length) => { TyArray(ref ty, length) => {
use rustc::middle::const_val::eval_length; use rustc::middle::const_val::eval_length;
let n = eval_length(cx.tcx, length, "array length").unwrap(); 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)), TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(hir::QPath::Resolved(None, ref path)) => { 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::TyFloat(float_ty) => Primitive(float_ty.into()),
ty::TyStr => Primitive(PrimitiveType::Str), ty::TyStr => Primitive(PrimitiveType::Str),
ty::TySlice(ty) => Slice(box ty.clean(cx)), 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::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
ty::TyRef(r, mt) => BorrowedRef { ty::TyRef(r, mt) => BorrowedRef {
lifetime: r.clean(cx), lifetime: r.clean(cx),

View file

@ -32,6 +32,7 @@ extern crate html_diff;
extern crate libc; extern crate libc;
extern crate rustc; extern crate rustc;
extern crate rustc_data_structures; extern crate rustc_data_structures;
extern crate rustc_const_math;
extern crate rustc_trans; extern crate rustc_trans;
extern crate rustc_driver; extern crate rustc_driver;
extern crate rustc_resolve; extern crate rustc_resolve;