Skip to content

Commit d4d6260

Browse files
committed
don't be a breaking change, even in presence of overflowing literals
1 parent 7003ed3 commit d4d6260

File tree

6 files changed

+57
-83
lines changed

6 files changed

+57
-83
lines changed

src/librustc/middle/const_eval.rs

+37-73
Original file line numberDiff line numberDiff line change
@@ -855,10 +855,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
855855
debug!("const call({:?})", call_args);
856856
try!(eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args)))
857857
},
858-
hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety, lit.span) {
859-
Ok(val) => val,
860-
Err(err) => signal!(e, Math(err)),
861-
},
858+
hir::ExprLit(ref lit) => try!(lit_to_const(&lit.node, tcx, ety, lit.span)),
862859
hir::ExprBlock(ref block) => {
863860
match block.expr {
864861
Some(ref expr) => try!(eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)),
@@ -926,7 +923,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
926923
if let Tuple(tup_id) = c {
927924
if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node {
928925
if index.node < fields.len() {
929-
return eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args)
926+
try!(eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args))
930927
} else {
931928
signal!(e, TupleIndexOutOfBounds);
932929
}
@@ -947,7 +944,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
947944
// if the idents are compared run-pass/issue-19244 fails
948945
if let Some(f) = fields.iter().find(|f| f.name.node
949946
== field_name.node) {
950-
return eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args)
947+
try!(eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args))
951948
} else {
952949
signal!(e, MissingStructField);
953950
}
@@ -974,22 +971,6 @@ fn infer<'tcx>(
974971
span: Span
975972
) -> Result<ConstInt, ConstEvalErr> {
976973
use syntax::ast::*;
977-
const I8MAX: u64 = ::std::i8::MAX as u64;
978-
const I16MAX: u64 = ::std::i16::MAX as u64;
979-
const I32MAX: u64 = ::std::i32::MAX as u64;
980-
const I64MAX: u64 = ::std::i64::MAX as u64;
981-
982-
const U8MAX: u64 = ::std::u8::MAX as u64;
983-
const U16MAX: u64 = ::std::u16::MAX as u64;
984-
const U32MAX: u64 = ::std::u32::MAX as u64;
985-
986-
const I8MAXI: i64 = ::std::i8::MAX as i64;
987-
const I16MAXI: i64 = ::std::i16::MAX as i64;
988-
const I32MAXI: i64 = ::std::i32::MAX as i64;
989-
990-
const I8MINI: i64 = ::std::i8::MIN as i64;
991-
const I16MINI: i64 = ::std::i16::MIN as i64;
992-
const I32MINI: i64 = ::std::i32::MIN as i64;
993974

994975
let err = |e| ConstEvalErr {
995976
span: span,
@@ -1009,41 +990,38 @@ fn infer<'tcx>(
1009990
(&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result),
1010991
(&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result),
1011992

1012-
(&ty::TyInt(IntTy::I8), Infer(i @ 0...I8MAX)) => Ok(I8(i as i8)),
1013-
(&ty::TyInt(IntTy::I16), Infer(i @ 0...I16MAX)) => Ok(I16(i as i16)),
1014-
(&ty::TyInt(IntTy::I32), Infer(i @ 0...I32MAX)) => Ok(I32(i as i32)),
1015-
(&ty::TyInt(IntTy::I64), Infer(i @ 0...I64MAX)) => Ok(I64(i as i64)),
1016-
(&ty::TyInt(IntTy::Is), Infer(i @ 0...I64MAX)) => {
993+
(&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i64 as i8)),
994+
(&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i64 as i16)),
995+
(&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i64 as i32)),
996+
(&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i64)),
997+
(&ty::TyInt(IntTy::Is), Infer(i)) => {
1017998
match ConstIsize::new(i as i64, tcx.sess.target.int_type) {
1018999
Ok(val) => Ok(Isize(val)),
1019-
Err(e) => Err(err(e.into())),
1000+
Err(_) => Ok(Isize(ConstIsize::Is32(i as i64 as i32))),
10201001
}
10211002
},
1022-
(&ty::TyInt(_), Infer(_)) => Err(err(Math(ConstMathErr::NotInRange))),
10231003

1024-
(&ty::TyInt(IntTy::I8), InferSigned(i @ I8MINI...I8MAXI)) => Ok(I8(i as i8)),
1025-
(&ty::TyInt(IntTy::I16), InferSigned(i @ I16MINI...I16MAXI)) => Ok(I16(i as i16)),
1026-
(&ty::TyInt(IntTy::I32), InferSigned(i @ I32MINI...I32MAXI)) => Ok(I32(i as i32)),
1004+
(&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)),
1005+
(&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)),
1006+
(&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)),
10271007
(&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i)),
10281008
(&ty::TyInt(IntTy::Is), InferSigned(i)) => {
10291009
match ConstIsize::new(i, tcx.sess.target.int_type) {
10301010
Ok(val) => Ok(Isize(val)),
1031-
Err(e) => Err(err(e.into())),
1011+
Err(_) => Ok(Isize(ConstIsize::Is32(i as i32))),
10321012
}
10331013
},
1034-
(&ty::TyInt(_), InferSigned(_)) => Err(err(Math(ConstMathErr::NotInRange))),
10351014

1036-
(&ty::TyUint(UintTy::U8), Infer(i @ 0...U8MAX)) => Ok(U8(i as u8)),
1037-
(&ty::TyUint(UintTy::U16), Infer(i @ 0...U16MAX)) => Ok(U16(i as u16)),
1038-
(&ty::TyUint(UintTy::U32), Infer(i @ 0...U32MAX)) => Ok(U32(i as u32)),
1015+
(&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)),
1016+
(&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)),
1017+
(&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)),
10391018
(&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i)),
10401019
(&ty::TyUint(UintTy::Us), Infer(i)) => {
10411020
match ConstUsize::new(i, tcx.sess.target.uint_type) {
10421021
Ok(val) => Ok(Usize(val)),
1043-
Err(e) => Err(err(e.into())),
1022+
Err(_) => Ok(Usize(ConstUsize::Us32(i as u32))),
10441023
}
10451024
},
1046-
(&ty::TyUint(_), Infer(_)) => Err(err(Math(ConstMathErr::NotInRange))),
10471025
(&ty::TyUint(_), InferSigned(_)) => Err(err(IntermediateUnsignedNegative)),
10481026

10491027
(&ty::TyInt(ity), i) => Err(err(TypeMismatch(ity.to_string(), i))),
@@ -1115,19 +1093,25 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
11151093
match ty.sty {
11161094
ty::TyBool if v == 0 => Ok(Bool(false)),
11171095
ty::TyBool if v == 1 => Ok(Bool(true)),
1118-
ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i8))),
1119-
ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i16))),
1120-
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i32))),
1096+
ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i64 as i8))),
1097+
ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i64 as i16))),
1098+
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i64 as i32))),
11211099
ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i64))),
11221100
ty::TyInt(ast::IntTy::Is) => {
1123-
Ok(Integral(Isize(try!(ConstIsize::new(v as i64, tcx.sess.target.int_type)))))
1101+
match ConstIsize::new(v as i64, tcx.sess.target.int_type) {
1102+
Ok(val) => Ok(Integral(Isize(val))),
1103+
Err(_) => Ok(Integral(Isize(ConstIsize::Is32(v as i64 as i32)))),
1104+
}
11241105
},
11251106
ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
11261107
ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))),
11271108
ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
1128-
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
1109+
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v))),
11291110
ty::TyUint(ast::UintTy::Us) => {
1130-
Ok(Integral(Usize(try!(ConstUsize::new(v, tcx.sess.target.uint_type)))))
1111+
match ConstUsize::new(v, tcx.sess.target.uint_type) {
1112+
Ok(val) => Ok(Integral(Usize(val))),
1113+
Err(_) => Ok(Integral(Usize(ConstUsize::Us32(v as u32)))),
1114+
}
11311115
},
11321116
ty::TyFloat(ast::FloatTy::F64) if val.is_negative() => {
11331117
// FIXME: this could probably be prettier
@@ -1174,57 +1158,37 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
11741158
tcx: &TyCtxt<'tcx>,
11751159
ty_hint: Option<Ty<'tcx>>,
11761160
span: Span,
1177-
) -> Result<ConstVal, ConstMathErr> {
1161+
) -> Result<ConstVal, ConstEvalErr> {
11781162
use syntax::ast::*;
11791163
use syntax::ast::LitIntType::*;
1180-
const I8MAX: u64 = ::std::i8::MAX as u64;
1181-
const I16MAX: u64 = ::std::i16::MAX as u64;
1182-
const I32MAX: u64 = ::std::i32::MAX as u64;
1183-
const I64MAX: u64 = ::std::i64::MAX as u64;
1184-
const U8MAX: u64 = ::std::u8::MAX as u64;
1185-
const U16MAX: u64 = ::std::u16::MAX as u64;
1186-
const U32MAX: u64 = ::std::u32::MAX as u64;
1187-
const U64MAX: u64 = ::std::u64::MAX as u64;
11881164
match *lit {
11891165
LitKind::Str(ref s, _) => Ok(Str((*s).clone())),
11901166
LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
11911167
LitKind::Byte(n) => Ok(Integral(U8(n))),
1192-
LitKind::Int(n @ 0...I8MAX, Signed(IntTy::I8)) => Ok(Integral(I8(n as i8))),
1193-
LitKind::Int(n @ 0...I16MAX, Signed(IntTy::I16)) => Ok(Integral(I16(n as i16))),
1194-
LitKind::Int(n @ 0...I32MAX, Signed(IntTy::I32)) => Ok(Integral(I32(n as i32))),
1195-
LitKind::Int(n @ 0...I64MAX, Signed(IntTy::I64)) => Ok(Integral(I64(n as i64))),
1196-
LitKind::Int(n, Signed(IntTy::Is)) => {
1197-
Ok(Integral(Isize(try!(ConstIsize::new(n as i64, tcx.sess.target.int_type)))))
1168+
LitKind::Int(n, Signed(ity)) => {
1169+
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity), span).map(Integral)
11981170
},
11991171

1200-
LitKind::Int(_, Signed(ty)) => Err(ConstMathErr::LitOutOfRange(ty)),
1201-
12021172
LitKind::Int(n, Unsuffixed) => {
12031173
match ty_hint.map(|t| &t.sty) {
12041174
Some(&ty::TyInt(ity)) => {
1205-
lit_to_const(&LitKind::Int(n, Signed(ity)), tcx, ty_hint, span)
1175+
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity), span).map(Integral)
12061176
},
12071177
Some(&ty::TyUint(uty)) => {
1208-
lit_to_const(&LitKind::Int(n, Unsigned(uty)), tcx, ty_hint, span)
1178+
infer(Infer(n), tcx, &ty::TyUint(uty), span).map(Integral)
12091179
},
12101180
None => Ok(Integral(Infer(n))),
12111181
Some(&ty::TyEnum(ref adt, _)) => {
12121182
let hints = tcx.lookup_repr_hints(adt.did);
12131183
let int_ty = tcx.enum_repr_type(hints.iter().next());
1214-
lit_to_const(lit, tcx, Some(int_ty.to_ty(tcx)), span)
1184+
infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty, span).map(Integral)
12151185
},
12161186
Some(ty_hint) => panic!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
12171187
}
12181188
},
1219-
LitKind::Int(n @ 0...U8MAX, Unsigned(UintTy::U8)) => Ok(Integral(U8(n as u8))),
1220-
LitKind::Int(n @ 0...U16MAX, Unsigned(UintTy::U16)) => Ok(Integral(U16(n as u16))),
1221-
LitKind::Int(n @ 0...U32MAX, Unsigned(UintTy::U32)) => Ok(Integral(U32(n as u32))),
1222-
LitKind::Int(n @ 0...U64MAX, Unsigned(UintTy::U64)) => Ok(Integral(U64(n as u64))),
1223-
1224-
LitKind::Int(n, Unsigned(UintTy::Us)) => {
1225-
Ok(Integral(Usize(try!(ConstUsize::new(n as u64, tcx.sess.target.uint_type)))))
1189+
LitKind::Int(n, Unsigned(ity)) => {
1190+
infer(Infer(n), tcx, &ty::TyUint(ity), span).map(Integral)
12261191
},
1227-
LitKind::Int(_, Unsigned(ty)) => Err(ConstMathErr::ULitOutOfRange(ty)),
12281192

12291193
LitKind::Float(ref n, _) |
12301194
LitKind::FloatUnsuffixed(ref n) => {

src/librustc_const_eval/int.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ impl ConstInt {
7373
(_, InferSigned(_))
7474
| (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)),
7575

76-
(Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i8),
77-
(Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i16),
78-
(Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i32),
76+
(Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8),
77+
(Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16),
78+
(Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32),
7979
(Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64),
80-
(Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i32)),
80+
(Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
8181
(Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
8282
(Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8),
8383
(Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16),

src/test/compile-fail/enum-discrim-too-small2.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,35 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#![deny(overflowing_literals)]
12+
#![allow(dead_code)]
13+
1114
#[repr(i8)]
1215
enum Ei8 {
1316
Ai8 = 23,
1417
Bi8 = -23,
15-
Ci8 = 223, //~ ERROR literal out of range for i8 [E0080]
18+
Ci8 = 223, //~ ERROR literal out of range for i8
1619
}
1720

1821
#[repr(i16)]
1922
enum Ei16 {
2023
Ai16 = 23,
2124
Bi16 = -22333,
22-
Ci16 = 55555, //~ ERROR literal out of range for i16 [E0080]
25+
Ci16 = 55555, //~ ERROR literal out of range for i16
2326
}
2427

2528
#[repr(i32)]
2629
enum Ei32 {
2730
Ai32 = 23,
2831
Bi32 = -2_000_000_000,
29-
Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32 [E0080]
32+
Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32
3033
}
3134

3235
#[repr(i64)]
3336
enum Ei64 {
3437
Ai64 = 23,
3538
Bi64 = -9223372036854775808,
36-
Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64 [E0080]
39+
Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64
3740
}
3841

3942
// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a

src/test/compile-fail/lint-type-limits2.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ fn bar() -> i8 {
1919
}
2020

2121
fn baz() -> bool {
22-
128 > bar() //~ ERROR literal out of range for i8
22+
128 > bar() //~ ERROR comparison is useless due to type limits
23+
//~| WARN literal out of range for i8
2324
}

src/test/compile-fail/lint-type-limits3.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ fn main() { }
1515

1616
fn qux() {
1717
let mut i = 1i8;
18-
while 200 != i { //~ ERROR literal out of range for i8
18+
while 200 != i { //~ ERROR comparison is useless due to type limits
19+
//~| WARN literal out of range for i8
1920
i += 1;
2021
}
2122
}

src/test/run-pass/const-negation.rs

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#![feature(stmt_expr_attributes)]
12+
1113
#[deny(const_err)]
1214

1315
fn main() {
@@ -18,7 +20,10 @@ fn main() {
1820
assert_eq!(::std::i32::MIN as u64, 0xffffffff80000000);
1921
assert_eq!(-2147483648isize as u64, 0xffffffff80000000);
2022
assert_eq!(::std::i64::MIN as u64, 0x8000000000000000);
23+
#[cfg(target_pointer_width = "64")]
2124
assert_eq!(-9223372036854775808isize as u64, 0x8000000000000000);
25+
#[cfg(target_pointer_width = "32")]
26+
assert_eq!(-9223372036854775808isize as u64, 0);
2227
const J: usize = ::std::i32::MAX as usize;
2328
const K: usize = -1i32 as u32 as usize;
2429
const L: usize = ::std::i32::MIN as usize;

0 commit comments

Comments
 (0)