From 54b15c7160e165621f0a7ae6a71db30dded254df Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 25 Feb 2016 10:14:10 +0100 Subject: [PATCH] the type hint given during a cast operation is just a soft hint --- src/librustc/middle/const_eval.rs | 16 +++++++++++++++- src/librustc_const_eval/int.rs | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 66ec1d691490..f4c5196d0cdb 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -743,7 +743,21 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>, } }; - 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 }), diff --git a/src/librustc_const_eval/int.rs b/src/librustc_const_eval/int.rs index 896d4a9b7d5e..bb72711379ea 100644 --- a/src/librustc_const_eval/int.rs +++ b/src/librustc_const_eval/int.rs @@ -9,6 +9,8 @@ // except according to those terms. use std::cmp::Ordering; +use syntax::attr::IntType; +use syntax::ast::{IntTy, UintTy}; use super::is::*; use super::us::*; @@ -258,6 +260,22 @@ impl ConstInt { ConstInt::Infer(_) | ConstInt::InferSigned(_) => panic!("no type info for const int"), } } + + pub fn int_type(self) -> Option { + 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 {