Don't abort on unevaluated constants without at least tryting to eval them

This commit is contained in:
Oliver Scherer 2019-03-22 18:30:35 +01:00
parent 437f017e2e
commit 9b87d22ea8
33 changed files with 80 additions and 64 deletions

View File

@ -896,7 +896,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
// Always promote `[T; 0]` (even when e.g., borrowed mutably).
let promotable = match expr_ty.sty {
ty::Array(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
ty::Array(_, len) if len.try_eval_usize(self.tcx) == Some(0) => true,
_ => promotable,
};

View File

@ -90,7 +90,7 @@ impl<'tcx> PlaceTy<'tcx> {
ProjectionElem::Subslice { from, to } => {
PlaceTy::from_ty(match self.ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let size = size.eval_usize(tcx);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
}

View File

@ -417,7 +417,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
));
let tcx = self.tcx;
if let Some(len) = len.assert_usize(tcx) {
if let Some(len) = len.try_eval_usize(tcx) {
flags.push((
sym::_Self,
Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),

View File

@ -194,7 +194,7 @@ impl<'tcx> ty::TyS<'tcx> {
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
ty::Array(_, n) => {
let n = tcx.lift_to_global(&n).unwrap();
match n.assert_usize(tcx) {
match n.try_eval_usize(tcx) {
Some(n) => format!("array of {} elements", n).into(),
None => "array".into(),
}

View File

@ -190,7 +190,7 @@ impl<'tcx> TyS<'tcx> {
}))
}
Array(ty, len) => match len.assert_usize(tcx) {
Array(ty, len) => match len.try_eval_usize(tcx) {
// If the array is definitely non-empty, it's uninhabited if
// the type of its elements is uninhabited.
Some(n) if n != 0 => ty.uninhabited_from(tcx),

View File

@ -594,7 +594,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
}
let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?;
let count = count.try_eval_usize(tcx).ok_or(LayoutError::Unknown(ty))?;
let element = self.layout_of(element)?;
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;

View File

@ -2368,7 +2368,7 @@ impl<'tcx> AdtDef {
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => {
// FIXME: Find the right type and use it instead of `val.ty` here
if let Some(b) = val.assert_bits(tcx.global_tcx(), val.ty) {
if let Some(b) = val.try_eval_bits(tcx.global_tcx(), val.ty) {
trace!("discriminants: {} ({:?})", b, repr_type);
Some(Discr {
val: b,

View File

@ -89,7 +89,7 @@ impl DefPathBasedNames<'tcx> {
ty::Array(inner_type, len) => {
output.push('[');
self.push_type_name(inner_type, output, debug);
write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
write!(output, "; {}", len.eval_usize(self.tcx)).unwrap();
output.push(']');
}
ty::Slice(inner_type) => {

View File

@ -696,7 +696,7 @@ pub trait PrettyPrinter<'tcx>:
},
ty::Array(ty, sz) => {
p!(write("["), print(ty), write("; "));
if let Some(n) = sz.assert_usize(self.tcx()) {
if let Some(n) = sz.try_eval_usize(self.tcx()) {
p!(write("{}", n));
} else {
p!(write("_"));
@ -915,7 +915,7 @@ pub trait PrettyPrinter<'tcx>:
if let ty::Ref(_, ref_ty, _) = ct.ty.sty {
let byte_str = match (ct.val, &ref_ty.sty) {
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
let n = n.unwrap_usize(self.tcx());
let n = n.eval_usize(self.tcx());
Some(self.tcx()
.alloc_map.lock()
.unwrap_memory(ptr.alloc_id)

View File

@ -466,7 +466,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
match (sz_a.assert_usize(tcx), sz_b.assert_usize(tcx)) {
match (sz_a.try_eval_usize(tcx), sz_b.try_eval_usize(tcx)) {
(Some(sz_a_val), Some(sz_b_val)) => {
Err(TypeError::FixedArraySize(
expected_found(relation, &sz_a_val, &sz_b_val)

View File

@ -15,7 +15,7 @@ use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFolda
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
use crate::ty::layout::VariantIdx;
use crate::util::captures::Captures;
use crate::mir::interpret::Scalar;
use crate::mir::interpret::{Scalar, GlobalId};
use smallvec::SmallVec;
use std::borrow::Cow;
@ -1726,7 +1726,7 @@ impl<'tcx> TyS<'tcx> {
ty.expect_ty().conservative_is_privately_uninhabited(tcx)
}),
ty::Array(ty, len) => {
match len.assert_usize(tcx) {
match len.try_eval_usize(tcx) {
// If the array is definitely non-empty, it's uninhabited if
// the type of its elements is uninhabited.
Some(n) if n != 0 => ty.conservative_is_privately_uninhabited(tcx),
@ -2291,16 +2291,32 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<u128> {
pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<u128> {
assert_eq!(self.ty, ty);
let ty = tcx.lift_to_global(&ty).unwrap();
// FIXME(eddyb, oli-obk) get the right param_env.
let size = tcx.layout_of(ParamEnv::empty().and(ty)).ok()?.size;
self.val.try_to_bits(size)
match self.val {
// FIXME(const_generics): this doesn't work right now,
// because it tries to relate an `Infer` to a `Param`.
ConstValue::Unevaluated(did, substs) => {
let substs = tcx.lift_to_global(&substs).unwrap();
let instance = ty::Instance::resolve(tcx, ParamEnv::empty(), did, substs)?;
let gid = GlobalId {
instance,
promoted: None,
};
let evaluated = tcx.const_eval(ParamEnv::empty().and(gid)).ok()?;
evaluated.val.try_to_bits(size)
},
// FIXME(const_generics): try to evaluate generic consts with a given param env?
// E.g. when you have an associated constant whose value depends on a generic const
_ => self.val.try_to_bits(size),
}
}
#[inline]
pub fn assert_bool(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
self.assert_bits(tcx, tcx.types.bool).and_then(|v| match v {
pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
self.try_eval_bits(tcx, tcx.types.bool).and_then(|v| match v {
0 => Some(false),
1 => Some(true),
_ => None,
@ -2308,19 +2324,19 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
pub fn assert_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.assert_bits(tcx, tcx.types.usize).map(|v| v as u64)
pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_eval_bits(tcx, tcx.types.usize).map(|v| v as u64)
}
#[inline]
pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 {
self.assert_bits(tcx, ty).unwrap_or_else(||
pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 {
self.try_eval_bits(tcx, ty).unwrap_or_else(||
bug!("expected bits of {}, got {:#?}", ty, self))
}
#[inline]
pub fn unwrap_usize(&self, tcx: TyCtxt<'tcx>) -> u64 {
self.unwrap_bits(tcx, tcx.types.usize) as u64
pub fn eval_usize(&self, tcx: TyCtxt<'tcx>) -> u64 {
self.eval_bits(tcx, tcx.types.usize) as u64
}
}

View File

@ -341,7 +341,7 @@ fn fixed_vec_metadata(
let (size, align) = cx.size_and_align_of(array_or_slice_type);
let upper_bound = match array_or_slice_type.sty {
ty::Array(_, len) => len.unwrap_usize(cx.tcx) as c_longlong,
ty::Array(_, len) => len.eval_usize(cx.tcx) as c_longlong,
_ => -1
};

View File

@ -132,7 +132,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, cx.param_env());
match (&source.sty, &target.sty) {
(&ty::Array(_, len), &ty::Slice(_)) => {
cx.const_usize(len.unwrap_usize(cx.tcx()))
cx.const_usize(len.eval_usize(cx.tcx()))
}
(&ty::Dynamic(..), &ty::Dynamic(..)) => {
// For now, upcasts are limited to changes in marker

View File

@ -89,7 +89,7 @@ pub fn push_debuginfo_type_name<'tcx>(
ty::Array(inner_type, len) => {
output.push('[');
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
output.push_str(&format!("; {}", len.unwrap_usize(tcx)));
output.push_str(&format!("; {}", len.eval_usize(tcx)));
output.push(']');
},
ty::Slice(inner_type) => {

View File

@ -41,7 +41,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.map(|c| {
let field_ty = c.ty.builtin_index().unwrap();
let fields = match c.ty.sty {
ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
ty::Array(_, n) => n.eval_usize(bx.tcx()),
_ => bug!("invalid simd shuffle type: {}", c.ty),
};
let values: Vec<_> = (0..fields).map(|field| {

View File

@ -521,7 +521,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} = *place {
if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::Array(_, n) = op.layout.ty.sty {
let n = n.unwrap_usize(bx.cx().tcx());
let n = n.eval_usize(bx.cx().tcx());
return bx.cx().const_usize(n);
}
}

View File

@ -512,7 +512,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
}
self = ct.ty.print(self)?;
if let Some(bits) = ct.assert_bits(self.tcx, ty::ParamEnv::empty().and(ct.ty)) {
if let Some(bits) = ct.try_eval_bits(self.tcx, ct.ty) {
let _ = write!(self.out, "{:x}_", bits);
} else {
// NOTE(eddyb) despite having the path, we need to

View File

@ -208,7 +208,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
}
has_emitted
}
ty::Array(ty, len) => match len.assert_usize(cx.tcx) {
ty::Array(ty, len) => match len.try_eval_usize(cx.tcx) {
// If the array is definitely non-empty, we can do `#[must_use]` checking.
Some(n) if n != 0 => {
let descr_pre = &format!(

View File

@ -669,7 +669,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
ProjectionElem::Subslice { from, to } => PlaceTy::from_ty(
match base_ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let size = size.eval_usize(tcx);
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)

View File

@ -339,7 +339,7 @@ fn place_base_conflict<'tcx>(
(StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
if promoted_1 == promoted_2 {
if let ty::Array(_, len) = s1.ty.sty {
if let Some(0) = len.assert_usize(tcx) {
if let Some(0) = len.try_eval_usize(tcx) {
// Ignore conflicts with promoted [T; 0].
debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
return Overlap::Disjoint;

View File

@ -111,7 +111,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatternKind::Constant { value } => {
indices.entry(value)
.or_insert_with(|| {
options.push(value.unwrap_bits(self.hir.tcx(), switch_ty));
options.push(value.eval_bits(self.hir.tcx(), switch_ty));
options.len() - 1
});
true

View File

@ -556,7 +556,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
};
let span = cx.tcx.def_span(def_id);
let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
Ok(cv) => cv.unwrap_usize(cx.tcx),
Ok(cv) => cv.eval_usize(cx.tcx),
Err(ErrorHandled::Reported) => 0,
Err(ErrorHandled::TooGeneric) => {
cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters");

View File

@ -228,7 +228,7 @@ impl LiteralExpander<'tcx> {
ConstValue::Slice {
data: self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id),
start: p.offset.bytes().try_into().unwrap(),
end: n.unwrap_usize(self.tcx).try_into().unwrap(),
end: n.eval_usize(self.tcx).try_into().unwrap(),
}
},
// fat pointers stay the same
@ -646,8 +646,8 @@ fn all_constructors<'a, 'tcx>(
ConstantValue(ty::Const::from_bool(cx.tcx, b))
}).collect()
}
ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => {
let len = len.unwrap_usize(cx.tcx);
ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx).is_some() => {
let len = len.eval_usize(cx.tcx);
if len != 0 && cx.is_uninhabited(sub_ty) {
vec![]
} else {
@ -789,7 +789,7 @@ where
match (value.val, &value.ty.sty) {
(_, ty::Array(_, n)) => max_fixed_len = cmp::max(
max_fixed_len,
n.unwrap_usize(cx.tcx),
n.eval_usize(cx.tcx),
),
(ConstValue::Slice{ start, end, .. }, ty::Slice(_)) => max_fixed_len = cmp::max(
max_fixed_len,
@ -856,7 +856,7 @@ impl<'tcx> IntRange<'tcx> {
}
ConstantValue(val) if is_integral(val.ty) => {
let ty = val.ty;
if let Some(val) = val.assert_bits(tcx, ty) {
if let Some(val) = val.try_eval_bits(tcx, ty) {
let bias = IntRange::signed_bias(tcx, ty);
let val = val ^ bias;
Some(IntRange { range: val..=val, ty })
@ -873,8 +873,8 @@ impl<'tcx> IntRange<'tcx> {
match pat.kind {
box PatternKind::Constant { value } => break ConstantValue(value),
box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange(
lo.unwrap_bits(tcx, ty),
hi.unwrap_bits(tcx, ty),
lo.eval_bits(tcx, ty),
hi.eval_bits(tcx, ty),
ty,
end,
),
@ -1327,14 +1327,14 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
Some(vec![ConstantRange(
lo.unwrap_bits(cx.tcx, ty),
hi.unwrap_bits(cx.tcx, ty),
lo.eval_bits(cx.tcx, ty),
hi.eval_bits(cx.tcx, ty),
ty,
end,
)]),
PatternKind::Array { .. } => match pcx.ty.sty {
ty::Array(_, length) => Some(vec![
Slice(length.unwrap_usize(cx.tcx))
Slice(length.eval_usize(cx.tcx))
]),
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
},
@ -1402,7 +1402,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx>(
match ty.sty {
// If the field type returned is an array of an unknown
// size return an TyErr.
ty::Array(_, len) if len.assert_usize(cx.tcx).is_none() =>
ty::Array(_, len) if len.try_eval_usize(cx.tcx).is_none() =>
cx.tcx.types.err,
_ => ty,
}
@ -1436,7 +1436,7 @@ fn slice_pat_covered_by_const<'tcx>(
let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
(ConstValue::ByRef { offset, alloc, .. }, ty::Array(t, n)) => {
assert_eq!(*t, tcx.types.u8);
let n = n.assert_usize(tcx).unwrap();
let n = n.eval_usize(tcx);
let ptr = Pointer::new(AllocId(0), offset);
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
},
@ -1464,7 +1464,7 @@ fn slice_pat_covered_by_const<'tcx>(
{
match pat.kind {
box PatternKind::Constant { value } => {
let b = value.unwrap_bits(tcx, pat.ty);
let b = value.eval_bits(tcx, pat.ty);
assert_eq!(b as u8 as u128, b);
if b as u8 != *ch {
return Ok(false);
@ -1760,7 +1760,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
ConstValue::ByRef { offset, alloc, .. } => (
alloc,
offset,
n.unwrap_usize(cx.tcx),
n.eval_usize(cx.tcx),
t,
),
_ => span_bug!(

View File

@ -728,7 +728,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
ty::Array(_, len) => {
// fixed-length array
let len = len.unwrap_usize(self.tcx);
let len = len.eval_usize(self.tcx);
assert!(len >= prefix.len() as u64 + suffix.len() as u64);
PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
}
@ -1123,7 +1123,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
}
ty::Array(_, n) => {
PatternKind::Array {
prefix: (0..n.unwrap_usize(self.tcx))
prefix: (0..n.eval_usize(self.tcx))
.map(|i| adt_subpattern(i as usize, None))
.collect(),
slice: None,
@ -1206,7 +1206,7 @@ fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>,
// (But still tell caller to continue search.)
return false;
}
ty::Array(_, n) if n.assert_usize(self.tcx) == Some(0) => {
ty::Array(_, n) if n.try_eval_usize(self.tcx) == Some(0) => {
// rust-lang/rust#62336: ignore type of contents
// for empty array.
return false;
@ -1470,7 +1470,7 @@ pub fn compare_const_vals<'tcx>(
return fallback();
}
if let (Some(a), Some(b)) = (a.assert_bits(tcx, ty), b.assert_bits(tcx, ty)) {
if let (Some(a), Some(b)) = (a.try_eval_bits(tcx, ty), b.try_eval_bits(tcx, ty)) {
use ::rustc_apfloat::Float;
return match ty.sty {
ty::Float(ast::FloatTy::F32) => {

View File

@ -253,7 +253,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// u64 cast is from usize to u64, which is always good
let val = Immediate::new_slice(
ptr,
length.unwrap_usize(self.tcx.tcx),
length.eval_usize(self.tcx.tcx),
self,
);
self.write_immediate(val, dest)

View File

@ -176,7 +176,7 @@ for
(InternMode::ConstBase, hir::Mutability::MutMutable) |
(InternMode::Const, hir::Mutability::MutMutable) => {
match referenced_ty.sty {
ty::Array(_, n) if n.unwrap_usize(self.ecx.tcx.tcx) == 0 => {}
ty::Array(_, n) if n.eval_usize(self.ecx.tcx.tcx) == 0 => {}
ty::Slice(_)
if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {}
_ => bug!("const qualif failed to prevent mutable references"),

View File

@ -313,7 +313,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
match self_ty.sty {
_ if is_copy => builder.copy_shim(),
ty::Array(ty, len) => {
let len = len.unwrap_usize(tcx);
let len = len.eval_usize(tcx);
builder.array_shim(dest, src, ty, len)
}
ty::Closure(def_id, substs) => {

View File

@ -367,7 +367,7 @@ impl Qualif for HasMutInterior {
} else if let ty::Array(_, len) = ty.sty {
// FIXME(eddyb) the `cx.mode == Mode::NonConstFn` condition
// seems unnecessary, given that this is merely a ZST.
match len.assert_usize(cx.tcx) {
match len.try_eval_usize(cx.tcx) {
Some(0) if cx.mode == Mode::NonConstFn => {},
_ => return true,
}

View File

@ -26,7 +26,7 @@ impl MirPass for SimplifyBranches {
TerminatorKind::SwitchInt {
discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, ..
} => {
let constant = c.literal.assert_bits(tcx, switch_ty);
let constant = c.literal.try_eval_bits(tcx, switch_ty);
if let Some(constant) = constant {
let (otherwise, targets) = targets.split_last().unwrap();
let mut ret = TerminatorKind::Goto { target: *otherwise };
@ -43,7 +43,7 @@ impl MirPass for SimplifyBranches {
},
TerminatorKind::Assert {
target, cond: Operand::Constant(ref c), expected, ..
} if (c.literal.assert_bool(tcx) == Some(true)) == expected =>
} if (c.literal.try_eval_bool(tcx) == Some(true)) == expected =>
TerminatorKind::Goto { target },
TerminatorKind::FalseEdges { real_target, .. } => {
TerminatorKind::Goto { target: real_target }

View File

@ -68,7 +68,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
let place_ty =
Place::ty_from(&src_place.base, &proj.base, self.body, self.tcx).ty;
if let ty::Array(item_ty, const_size) = place_ty.sty {
if let Some(size) = const_size.assert_usize(self.tcx) {
if let Some(size) = const_size.try_eval_usize(self.tcx) {
assert!(size <= u32::max_value() as u64,
"uniform array move out doesn't supported
for array bigger then u32");
@ -219,7 +219,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
let src_ty =
Place::ty_from(src_place.base, src_place.projection, body, tcx).ty;
if let ty::Array(_, ref size_o) = src_ty.sty {
size_o.assert_usize(tcx)
size_o.try_eval_usize(tcx)
} else {
None
}

View File

@ -821,7 +821,7 @@ where
self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
}
ty::Array(ety, size) => {
let size = size.assert_usize(self.tcx());
let size = size.try_eval_usize(self.tcx());
self.open_drop_for_array(ety, size)
},
ty::Slice(ety) => self.open_drop_for_array(ety, None),

View File

@ -423,7 +423,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expected_ty = self.structurally_resolved_type(pat.span, expected);
let (inner_ty, slice_ty) = match expected_ty.sty {
ty::Array(inner_ty, size) => {
if let Some(size) = size.assert_usize(tcx) {
if let Some(size) = size.try_eval_usize(tcx) {
let min_len = before.len() as u64 + after.len() as u64;
if slice.is_none() {
if min_len != size {

View File

@ -1386,7 +1386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ty::Array(_, len) => {
if let (Some(len), Ok(user_index)) = (
len.assert_usize(self.tcx),
len.try_eval_usize(self.tcx),
field.as_str().parse::<u64>()
) {
let base = self.tcx.sess.source_map()