diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 2a00724cafbe5..b0a48e87d9369 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -502,42 +502,44 @@ pub fn eval_const_expr_partial(tcx: &T, e: &Expr) const cast") }); - let base = eval_const_expr_partial(tcx, &**base); - match base { - Err(_) => base, - Ok(val) => { - match ty::get(ety).sty { - ty::ty_float(_) => { - match val { - const_bool(b) => Ok(const_float(b as f64)), - const_uint(u) => Ok(const_float(u as f64)), - const_int(i) => Ok(const_float(i as f64)), - const_float(f) => Ok(const_float(f)), - _ => Err("can't cast this type to float".to_string()), - } + macro_rules! define_casts( + ($val:ident, { + $($ty_pat:pat => ( + $intermediate_ty:ty, + $const_type:ident, + $target_ty:ty + )),* + }) => (match ty::get(ety).sty { + $($ty_pat => { + match $val { + const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)), + const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)), + const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)), + const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)), + _ => Err(concat!( + "can't cast this type to ", stringify!($const_type) + ).to_string()) } - ty::ty_uint(_) => { - match val { - const_bool(b) => Ok(const_uint(b as u64)), - const_uint(u) => Ok(const_uint(u)), - const_int(i) => Ok(const_uint(i as u64)), - const_float(f) => Ok(const_uint(f as u64)), - _ => Err("can't cast this type to uint".to_string()), - } - } - ty::ty_int(_) => { - match val { - const_bool(b) => Ok(const_int(b as i64)), - const_uint(u) => Ok(const_int(u as i64)), - const_int(i) => Ok(const_int(i)), - const_float(f) => Ok(const_int(f as i64)), - _ => Err("can't cast this type to int".to_string()), - } - } - _ => Err("can't cast this type".to_string()) - } - } - } + },)* + _ => Err("can't cast this type".to_string()) + }) + ) + + eval_const_expr_partial(tcx, &**base) + .and_then(|val| define_casts!(val, { + ty::ty_int(ast::TyI) => (int, const_int, i64), + ty::ty_int(ast::TyI8) => (i8, const_int, i64), + ty::ty_int(ast::TyI16) => (i16, const_int, i64), + ty::ty_int(ast::TyI32) => (i32, const_int, i64), + ty::ty_int(ast::TyI64) => (i64, const_int, i64), + ty::ty_uint(ast::TyU) => (uint, const_uint, u64), + ty::ty_uint(ast::TyU8) => (u8, const_uint, u64), + ty::ty_uint(ast::TyU16) => (u16, const_uint, u64), + ty::ty_uint(ast::TyU32) => (u32, const_uint, u64), + ty::ty_uint(ast::TyU64) => (u64, const_uint, u64), + ty::ty_float(ast::TyF32) => (f32, const_float, f64), + ty::ty_float(ast::TyF64) => (f64, const_float, f64) + })) } ExprPath(_) => { match lookup_const(tcx.ty_ctxt(), e) { diff --git a/src/test/run-pass/issue-17074.rs b/src/test/run-pass/issue-17074.rs new file mode 100644 index 0000000000000..e346148691d86 --- /dev/null +++ b/src/test/run-pass/issue-17074.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static X: u64 = -1 as u16 as u64; +static Y: u64 = -1 as u32 as u64; + +fn main() { + assert_eq!(match 1 { + X => unreachable!(), + Y => unreachable!(), + _ => 1i + }, 1); +}