}
};
- let val = try!(eval_const_expr_partial(tcx, &base, base_hint, fn_args));
+ let val = match eval_const_expr_partial(tcx, &base, base_hint, fn_args) {
+ Ok(val) => val,
+ Err(ConstEvalErr { kind: InferredWrongType(val), .. }) => {
+ // Something like `5i8 as usize` doesn't need a type hint for the base
+ // instead take the type hint from the inner value
+ let hint = match val.int_type() {
+ Some(IntType::UnsignedInt(ty)) => ty_hint.checked_or(tcx.mk_mach_uint(ty)),
+ Some(IntType::SignedInt(ty)) => ty_hint.checked_or(tcx.mk_mach_int(ty)),
+ // we had a type hint, so we can't have an unknown type
+ None => unreachable!(),
+ };
+ try!(eval_const_expr_partial(tcx, &base, hint, fn_args))
+ },
+ Err(e) => return Err(e),
+ };
match cast_const(tcx, val, ety) {
Ok(val) => val,
Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
// except according to those terms.
use std::cmp::Ordering;
+use syntax::attr::IntType;
+use syntax::ast::{IntTy, UintTy};
use super::is::*;
use super::us::*;
ConstInt::Infer(_) | ConstInt::InferSigned(_) => panic!("no type info for const int"),
}
}
+
+ pub fn int_type(self) -> Option<IntType> {
+ match self {
+ ConstInt::I8(_) => Some(IntType::SignedInt(IntTy::I8)),
+ ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)),
+ ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)),
+ ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)),
+ ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)),
+ ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)),
+ ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)),
+ ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)),
+ ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)),
+ ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)),
+ _ => None,
+ }
+ }
}
impl ::std::cmp::PartialOrd for ConstInt {