2022-02-26 07:26:21 -06:00
|
|
|
use clippy_utils::ty::{read_explicit_enum_value, EnumValue};
|
|
|
|
use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
|
2021-03-12 08:30:50 -06:00
|
|
|
|
|
|
|
/// Returns the size in bits of an integral type.
|
|
|
|
/// Will return 0 if the type is not an int or uint variant
|
|
|
|
pub(super) fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 {
|
|
|
|
match typ.kind() {
|
|
|
|
ty::Int(i) => match i {
|
|
|
|
IntTy::Isize => tcx.data_layout.pointer_size.bits(),
|
|
|
|
IntTy::I8 => 8,
|
|
|
|
IntTy::I16 => 16,
|
|
|
|
IntTy::I32 => 32,
|
|
|
|
IntTy::I64 => 64,
|
|
|
|
IntTy::I128 => 128,
|
|
|
|
},
|
|
|
|
ty::Uint(i) => match i {
|
|
|
|
UintTy::Usize => tcx.data_layout.pointer_size.bits(),
|
|
|
|
UintTy::U8 => 8,
|
|
|
|
UintTy::U16 => 16,
|
|
|
|
UintTy::U32 => 32,
|
|
|
|
UintTy::U64 => 64,
|
|
|
|
UintTy::U128 => 128,
|
|
|
|
},
|
|
|
|
_ => 0,
|
|
|
|
}
|
|
|
|
}
|
2022-02-26 07:26:21 -06:00
|
|
|
|
|
|
|
pub(super) fn enum_value_nbits(value: EnumValue) -> u64 {
|
|
|
|
match value {
|
|
|
|
EnumValue::Unsigned(x) => 128 - x.leading_zeros(),
|
|
|
|
EnumValue::Signed(x) if x < 0 => 128 - (-(x + 1)).leading_zeros() + 1,
|
|
|
|
EnumValue::Signed(x) => 128 - x.leading_zeros(),
|
|
|
|
}
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn enum_ty_to_nbits(adt: &AdtDef, tcx: TyCtxt<'_>) -> u64 {
|
|
|
|
let mut explicit = 0i128;
|
|
|
|
let (start, end) = adt
|
|
|
|
.variants
|
|
|
|
.iter()
|
|
|
|
.fold((0, i128::MIN), |(start, end), variant| match variant.discr {
|
|
|
|
VariantDiscr::Relative(x) => match explicit.checked_add(i128::from(x)) {
|
|
|
|
Some(x) => (start, end.max(x)),
|
|
|
|
None => (i128::MIN, end),
|
|
|
|
},
|
|
|
|
VariantDiscr::Explicit(id) => match read_explicit_enum_value(tcx, id) {
|
|
|
|
Some(EnumValue::Signed(x)) => {
|
|
|
|
explicit = x;
|
|
|
|
(start.min(x), end.max(x))
|
|
|
|
},
|
|
|
|
Some(EnumValue::Unsigned(x)) => match i128::try_from(x) {
|
|
|
|
Ok(x) => {
|
|
|
|
explicit = x;
|
|
|
|
(start, end.max(x))
|
|
|
|
},
|
|
|
|
Err(_) => (i128::MIN, end),
|
|
|
|
},
|
|
|
|
None => (start, end),
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
if start > end {
|
|
|
|
// No variants.
|
|
|
|
0
|
|
|
|
} else {
|
|
|
|
let neg_bits = if start < 0 {
|
|
|
|
128 - (-(start + 1)).leading_zeros() + 1
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
let pos_bits = if end > 0 { 128 - end.leading_zeros() } else { 0 };
|
|
|
|
neg_bits.max(pos_bits).into()
|
|
|
|
}
|
|
|
|
}
|