Skip to content

Commit 52f7e88

Browse files
committed
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
2 parents 5092c6b + b272749 commit 52f7e88

File tree

4 files changed

+66
-38
lines changed

4 files changed

+66
-38
lines changed

src/librustc/ty/layout.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1544,11 +1544,17 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
15441544
}
15451545

15461546
let (mut min, mut max) = (i128::max_value(), i128::min_value());
1547+
let discr_type = def.repr.discr_type();
1548+
let bits = Integer::from_attr(tcx, discr_type).size().bits();
15471549
for (i, discr) in def.discriminants(tcx).enumerate() {
15481550
if variants[i].iter().any(|f| f.abi == Abi::Uninhabited) {
15491551
continue;
15501552
}
1551-
let x = discr.val as i128;
1553+
let mut x = discr.val as i128;
1554+
if discr_type.is_signed() {
1555+
// sign extend the raw representation to be an i128
1556+
x = (x << (128 - bits)) >> (128 - bits);
1557+
}
15521558
if x < min { min = x; }
15531559
if x > max { max = x; }
15541560
}

src/librustc/ty/mod.rs

+5-18
Original file line numberDiff line numberDiff line change
@@ -1887,7 +1887,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
18871887
) -> Option<Discr<'tcx>> {
18881888
let param_env = ParamEnv::empty();
18891889
let repr_type = self.repr.discr_type();
1890-
let bit_size = layout::Integer::from_attr(tcx, repr_type).size().bits();
18911890
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
18921891
let instance = ty::Instance::new(expr_did, substs);
18931892
let cid = GlobalId {
@@ -1897,25 +1896,13 @@ impl<'a, 'gcx, 'tcx> AdtDef {
18971896
match tcx.const_eval(param_env.and(cid)) {
18981897
Ok(&ty::Const {
18991898
val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
1900-
..
1899+
ty,
19011900
}) => {
19021901
trace!("discriminants: {} ({:?})", b, repr_type);
1903-
let ty = repr_type.to_ty(tcx);
1904-
if repr_type.is_signed() {
1905-
let val = b as i128;
1906-
// sign extend to i128
1907-
let amt = 128 - bit_size;
1908-
let val = (val << amt) >> amt;
1909-
Some(Discr {
1910-
val: val as u128,
1911-
ty,
1912-
})
1913-
} else {
1914-
Some(Discr {
1915-
val: b,
1916-
ty,
1917-
})
1918-
}
1902+
Some(Discr {
1903+
val: b,
1904+
ty,
1905+
})
19191906
},
19201907
Ok(&ty::Const {
19211908
val: ConstVal::Value(other),

src/librustc/ty/util.rs

+27-19
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,24 @@ use syntax_pos::{Span, DUMMY_SP};
3939

4040
#[derive(Copy, Clone, Debug)]
4141
pub struct Discr<'tcx> {
42+
/// bit representation of the discriminant, so `-128i8` is `0xFF_u128`
4243
pub val: u128,
4344
pub ty: Ty<'tcx>
4445
}
4546

4647
impl<'tcx> fmt::Display for Discr<'tcx> {
4748
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
48-
if self.ty.is_signed() {
49-
write!(fmt, "{}", self.val as i128)
50-
} else {
51-
write!(fmt, "{}", self.val)
49+
match self.ty.sty {
50+
ty::TyInt(ity) => {
51+
let bits = ty::tls::with(|tcx| {
52+
Integer::from_attr(tcx, SignedInt(ity)).size().bits()
53+
});
54+
let x = self.val as i128;
55+
// sign extend the raw representation to be an i128
56+
let x = (x << (128 - bits)) >> (128 - bits);
57+
write!(fmt, "{}", x)
58+
},
59+
_ => write!(fmt, "{}", self.val),
5260
}
5361
}
5462
}
@@ -64,38 +72,38 @@ impl<'tcx> Discr<'tcx> {
6472
TyUint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false),
6573
_ => bug!("non integer discriminant"),
6674
};
75+
76+
let bit_size = int.size().bits();
77+
let amt = 128 - bit_size;
6778
if signed {
68-
let (min, max) = match int {
69-
Integer::I8 => (i8::min_value() as i128, i8::max_value() as i128),
70-
Integer::I16 => (i16::min_value() as i128, i16::max_value() as i128),
71-
Integer::I32 => (i32::min_value() as i128, i32::max_value() as i128),
72-
Integer::I64 => (i64::min_value() as i128, i64::max_value() as i128),
73-
Integer::I128 => (i128::min_value(), i128::max_value()),
79+
let sext = |u| {
80+
let i = u as i128;
81+
(i << amt) >> amt
7482
};
75-
let val = self.val as i128;
83+
let min = sext(1_u128 << (bit_size - 1));
84+
let max = i128::max_value() >> amt;
85+
let val = sext(self.val);
86+
assert!(n < (i128::max_value() as u128));
7687
let n = n as i128;
7788
let oflo = val > max - n;
7889
let val = if oflo {
7990
min + (n - (max - val) - 1)
8091
} else {
8192
val + n
8293
};
94+
// zero the upper bits
95+
let val = val as u128;
96+
let val = (val << amt) >> amt;
8397
(Self {
8498
val: val as u128,
8599
ty: self.ty,
86100
}, oflo)
87101
} else {
88-
let (min, max) = match int {
89-
Integer::I8 => (u8::min_value() as u128, u8::max_value() as u128),
90-
Integer::I16 => (u16::min_value() as u128, u16::max_value() as u128),
91-
Integer::I32 => (u32::min_value() as u128, u32::max_value() as u128),
92-
Integer::I64 => (u64::min_value() as u128, u64::max_value() as u128),
93-
Integer::I128 => (u128::min_value(), u128::max_value()),
94-
};
102+
let max = u128::max_value() >> amt;
95103
let val = self.val;
96104
let oflo = val > max - n;
97105
let val = if oflo {
98-
min + (n - (max - val) - 1)
106+
n - (max - val) - 1
99107
} else {
100108
val + n
101109
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// https://github.com/rust-lang/rust/issues/49181
12+
13+
#[derive(Eq, PartialEq)]
14+
#[repr(i8)]
15+
pub enum A {
16+
B = -1,
17+
C = 1,
18+
}
19+
20+
pub const D: A = A::B;
21+
22+
fn main() {
23+
match A::C {
24+
D => {},
25+
_ => {}
26+
}
27+
}

0 commit comments

Comments
 (0)