}
let (mut min, mut max) = (i128::max_value(), i128::min_value());
+ let discr_type = def.repr.discr_type();
+ let bits = Integer::from_attr(tcx, discr_type).size().bits();
for (i, discr) in def.discriminants(tcx).enumerate() {
if variants[i].iter().any(|f| f.abi == Abi::Uninhabited) {
continue;
}
- let x = discr.val as i128;
+ let mut x = discr.val as i128;
+ if discr_type.is_signed() {
+ // sign extend the raw representation to be an i128
+ x = (x << (128 - bits)) >> (128 - bits);
+ }
if x < min { min = x; }
if x > max { max = x; }
}
) -> Option<Discr<'tcx>> {
let param_env = ParamEnv::empty();
let repr_type = self.repr.discr_type();
- let bit_size = layout::Integer::from_attr(tcx, repr_type).size().bits();
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
let instance = ty::Instance::new(expr_did, substs);
let cid = GlobalId {
match tcx.const_eval(param_env.and(cid)) {
Ok(&ty::Const {
val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
- ..
+ ty,
}) => {
trace!("discriminants: {} ({:?})", b, repr_type);
- let ty = repr_type.to_ty(tcx);
- if repr_type.is_signed() {
- let val = b as i128;
- // sign extend to i128
- let amt = 128 - bit_size;
- let val = (val << amt) >> amt;
- Some(Discr {
- val: val as u128,
- ty,
- })
- } else {
- Some(Discr {
- val: b,
- ty,
- })
- }
+ Some(Discr {
+ val: b,
+ ty,
+ })
},
Ok(&ty::Const {
val: ConstVal::Value(other),
#[derive(Copy, Clone, Debug)]
pub struct Discr<'tcx> {
+ /// bit representation of the discriminant, so `-128i8` is `0xFF_u128`
pub val: u128,
pub ty: Ty<'tcx>
}
impl<'tcx> fmt::Display for Discr<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- if self.ty.is_signed() {
- write!(fmt, "{}", self.val as i128)
- } else {
- write!(fmt, "{}", self.val)
+ match self.ty.sty {
+ ty::TyInt(ity) => {
+ let bits = ty::tls::with(|tcx| {
+ Integer::from_attr(tcx, SignedInt(ity)).size().bits()
+ });
+ let x = self.val as i128;
+ // sign extend the raw representation to be an i128
+ let x = (x << (128 - bits)) >> (128 - bits);
+ write!(fmt, "{}", x)
+ },
+ _ => write!(fmt, "{}", self.val),
}
}
}
TyUint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false),
_ => bug!("non integer discriminant"),
};
+
+ let bit_size = int.size().bits();
+ let amt = 128 - bit_size;
if signed {
- let (min, max) = match int {
- Integer::I8 => (i8::min_value() as i128, i8::max_value() as i128),
- Integer::I16 => (i16::min_value() as i128, i16::max_value() as i128),
- Integer::I32 => (i32::min_value() as i128, i32::max_value() as i128),
- Integer::I64 => (i64::min_value() as i128, i64::max_value() as i128),
- Integer::I128 => (i128::min_value(), i128::max_value()),
+ let sext = |u| {
+ let i = u as i128;
+ (i << amt) >> amt
};
- let val = self.val as i128;
+ let min = sext(1_u128 << (bit_size - 1));
+ let max = i128::max_value() >> amt;
+ let val = sext(self.val);
+ assert!(n < (i128::max_value() as u128));
let n = n as i128;
let oflo = val > max - n;
let val = if oflo {
} else {
val + n
};
+ // zero the upper bits
+ let val = val as u128;
+ let val = (val << amt) >> amt;
(Self {
val: val as u128,
ty: self.ty,
}, oflo)
} else {
- let (min, max) = match int {
- Integer::I8 => (u8::min_value() as u128, u8::max_value() as u128),
- Integer::I16 => (u16::min_value() as u128, u16::max_value() as u128),
- Integer::I32 => (u32::min_value() as u128, u32::max_value() as u128),
- Integer::I64 => (u64::min_value() as u128, u64::max_value() as u128),
- Integer::I128 => (u128::min_value(), u128::max_value()),
- };
+ let max = u128::max_value() >> amt;
let val = self.val;
let oflo = val > max - n;
let val = if oflo {
- min + (n - (max - val) - 1)
+ n - (max - val) - 1
} else {
val + n
};
--- /dev/null
+// Copyright 2018 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// https://github.com/rust-lang/rust/issues/49181
+
+#[derive(Eq, PartialEq)]
+#[repr(i8)]
+pub enum A {
+ B = -1,
+ C = 1,
+}
+
+pub const D: A = A::B;
+
+fn main() {
+ match A::C {
+ D => {},
+ _ => {}
+ }
+}