]> git.lizzy.rs Git - rust.git/commitdiff
the type hint given during a cast operation is just a soft hint
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 25 Feb 2016 09:14:10 +0000 (10:14 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 10 Mar 2016 11:50:13 +0000 (12:50 +0100)
src/librustc/middle/const_eval.rs
src/librustc_const_eval/int.rs

index 66ec1d691490eb6ed76a40d7b70159a78885582a..f4c5196d0cdb5145f7735b20d6308df90e67b29a 100644 (file)
@@ -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 }),
index 896d4a9b7d5e2c38ee67fc0e2bf2db0fddafd1f9..bb72711379eaa35ff6e124b22eea4a31580f7d80 100644 (file)
@@ -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 @@ macro_rules! add1 {
             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 {