Auto merge of #49210 - oli-obk:pango_crash, r=eddyb
Fix the conversion between bit representations and i128 representations fixes #49181 the `Discr` type now encodes the bit representation instead of `i128` or `u128` casted to `u128`. r? @eddyb
This commit is contained in:
commit
52f7e8836c
|
@ -1544,11 +1544,17 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
|
|
|
@ -1887,7 +1887,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
) -> 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 {
|
||||
|
@ -1897,25 +1896,13 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
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),
|
||||
|
|
|
@ -39,16 +39,24 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||
|
||||
#[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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,15 +72,18 @@ impl<'tcx> Discr<'tcx> {
|
|||
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 {
|
||||
|
@ -80,22 +91,19 @@ impl<'tcx> Discr<'tcx> {
|
|||
} 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
|
||||
};
|
||||
|
|
27
src/test/run-pass/ctfe/signed_enum_discr.rs
Normal file
27
src/test/run-pass/ctfe/signed_enum_discr.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// 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 => {},
|
||||
_ => {}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue