Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change ConstInt impl to not rely on ScalarInt #96789

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,11 @@ impl<'tcx, Tag: Provenance> ImmTy<'tcx, Tag> {
pub fn to_const_int(self) -> ConstInt {
assert!(self.layout.ty.is_integral());
let int = self.to_scalar().expect("to_const_int doesn't work on scalar pairs").assert_int();
ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral())
ConstInt::new_with_width(
int.assert_bits(int.size()),
self.layout.ty,
int.size().bytes() as u32,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use as casts in the interpreter.

)
}
}

Expand Down
183 changes: 97 additions & 86 deletions compiler/rustc_middle/src/ty/consts/int.rs
Original file line number Diff line number Diff line change
@@ -1,113 +1,124 @@
use crate::ty::{self, Ty, TyCtxt};
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::Size;
use rustc_type_ir::{IntTy, UintTy};
use std::convert::{TryFrom, TryInto};
use std::fmt;

use crate::ty::TyCtxt;
#[derive(Copy, Clone)]
enum IntegerTy {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked, but there seem to be no existing enums like this. Surprising...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to refactor Ty to have a single Int variant with a field of this type, rather than 2 top-level Int and Uint variants.

Uint(UintTy),
Int(IntTy),
}

#[derive(Copy, Clone)]
/// A type for representing any integer. Only used for printing.
pub struct ConstInt {
/// The "untyped" variant of `ConstInt`.
int: ScalarInt,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this was going to get more reuse, looks like it never did

/// Whether the value is of a signed integer type.
signed: bool,
/// Whether the value is a `usize` or `isize` type.
is_ptr_sized_integral: bool,
pointer_width: u32,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this field do/mean? Please add a doc comment to each field.

/// The byte value of the integer.
value: u128,
ty: IntegerTy,
}

impl ConstInt {
pub fn new(int: ScalarInt, signed: bool, is_ptr_sized_integral: bool) -> Self {
Self { int, signed, is_ptr_sized_integral }
pub fn new(tcx: TyCtxt<'_>, value: u128, ty: Ty<'_>) -> Self {
Self::new_with_width(value, ty, tcx.sess.target.pointer_width)
}

pub fn new_with_width(value: u128, ty: Ty<'_>, pointer_width: u32) -> Self {
let ty = match *ty.kind() {
ty::Uint(uty) => IntegerTy::Uint(uty),
ty::Int(ity) => IntegerTy::Int(ity),
_ => bug!("unexpected type for ConstInt: {ty}"),
};

Self { pointer_width, value, ty }
}
}

impl std::fmt::Debug for ConstInt {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { int, signed, is_ptr_sized_integral } = *self;
let size = int.size().bytes();
let raw = int.data;
if signed {
let bit_size = size * 8;
let min = 1u128 << (bit_size - 1);
let max = min - 1;
if raw == min {
match (size, is_ptr_sized_integral) {
(_, true) => write!(fmt, "isize::MIN"),
(1, _) => write!(fmt, "i8::MIN"),
(2, _) => write!(fmt, "i16::MIN"),
(4, _) => write!(fmt, "i32::MIN"),
(8, _) => write!(fmt, "i64::MIN"),
(16, _) => write!(fmt, "i128::MIN"),
_ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
}
} else if raw == max {
match (size, is_ptr_sized_integral) {
(_, true) => write!(fmt, "isize::MAX"),
(1, _) => write!(fmt, "i8::MAX"),
(2, _) => write!(fmt, "i16::MAX"),
(4, _) => write!(fmt, "i32::MAX"),
(8, _) => write!(fmt, "i64::MAX"),
(16, _) => write!(fmt, "i128::MAX"),
_ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
}
} else {
match size {
1 => write!(fmt, "{}", raw as i8)?,
2 => write!(fmt, "{}", raw as i16)?,
4 => write!(fmt, "{}", raw as i32)?,
8 => write!(fmt, "{}", raw as i64)?,
16 => write!(fmt, "{}", raw as i128)?,
_ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
}
if fmt.alternate() {
match (size, is_ptr_sized_integral) {
(_, true) => write!(fmt, "_isize")?,
(1, _) => write!(fmt, "_i8")?,
(2, _) => write!(fmt, "_i16")?,
(4, _) => write!(fmt, "_i32")?,
(8, _) => write!(fmt, "_i64")?,
(16, _) => write!(fmt, "_i128")?,
_ => bug!(),
let ConstInt { pointer_width, value, ty } = *self;
match ty {
IntegerTy::Int(ity) => {
let size = ity.bit_width().unwrap_or(pointer_width as u64);
let min = 1u128 << (size * 8 - 1);
let max = min - 1;
if value == min {
match ity {
IntTy::Isize => write!(fmt, "isize::MIN"),
IntTy::I8 => write!(fmt, "i8::MIN"),
IntTy::I16 => write!(fmt, "i16::MIN"),
IntTy::I32 => write!(fmt, "i32::MIN"),
IntTy::I64 => write!(fmt, "i64::MIN"),
IntTy::I128 => write!(fmt, "i128::MIN"),
}
} else if value == max {
match ity {
IntTy::Isize => write!(fmt, "isize::MAX"),
IntTy::I8 => write!(fmt, "i8::MAX"),
IntTy::I16 => write!(fmt, "i16::MAX"),
IntTy::I32 => write!(fmt, "i32::MAX"),
IntTy::I64 => write!(fmt, "i64::MAX"),
IntTy::I128 => write!(fmt, "i128::MAX"),
}
} else {
match size {
1 => write!(fmt, "{}", value as i8)?,
2 => write!(fmt, "{}", value as i16)?,
4 => write!(fmt, "{}", value as i32)?,
8 => write!(fmt, "{}", value as i64)?,
16 => write!(fmt, "{}", value as i128)?,
_ => bug!("signed ConstInt 0x{value:x} of size {size}"),
}
if fmt.alternate() {
match ity {
IntTy::Isize => write!(fmt, "_isize")?,
IntTy::I8 => write!(fmt, "_i8")?,
IntTy::I16 => write!(fmt, "_i16")?,
IntTy::I32 => write!(fmt, "_i32")?,
IntTy::I64 => write!(fmt, "_i64")?,
IntTy::I128 => write!(fmt, "_i128")?,
}
}
Ok(())
}
Ok(())
}
} else {
let max = Size::from_bytes(size).truncate(u128::MAX);
if raw == max {
match (size, is_ptr_sized_integral) {
(_, true) => write!(fmt, "usize::MAX"),
(1, _) => write!(fmt, "u8::MAX"),
(2, _) => write!(fmt, "u16::MAX"),
(4, _) => write!(fmt, "u32::MAX"),
(8, _) => write!(fmt, "u64::MAX"),
(16, _) => write!(fmt, "u128::MAX"),
_ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
}
} else {
match size {
1 => write!(fmt, "{}", raw as u8)?,
2 => write!(fmt, "{}", raw as u16)?,
4 => write!(fmt, "{}", raw as u32)?,
8 => write!(fmt, "{}", raw as u64)?,
16 => write!(fmt, "{}", raw as u128)?,
_ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
}
if fmt.alternate() {
match (size, is_ptr_sized_integral) {
(_, true) => write!(fmt, "_usize")?,
(1, _) => write!(fmt, "_u8")?,
(2, _) => write!(fmt, "_u16")?,
(4, _) => write!(fmt, "_u32")?,
(8, _) => write!(fmt, "_u64")?,
(16, _) => write!(fmt, "_u128")?,
_ => bug!(),
IntegerTy::Uint(uty) => {
let size = uty.bit_width().unwrap_or(pointer_width.into());
let max = Size::from_bytes(size).truncate(u128::MAX);
if value == max {
match uty {
UintTy::Usize => write!(fmt, "usize::MAX"),
UintTy::U8 => write!(fmt, "u8::MAX"),
UintTy::U16 => write!(fmt, "u16::MAX"),
UintTy::U32 => write!(fmt, "u32::MAX"),
UintTy::U64 => write!(fmt, "u64::MAX"),
UintTy::U128 => write!(fmt, "u128::MAX"),
}
} else {
match size {
1 => write!(fmt, "{}", value as u8)?,
2 => write!(fmt, "{}", value as u16)?,
4 => write!(fmt, "{}", value as u32)?,
8 => write!(fmt, "{}", value as u64)?,
16 => write!(fmt, "{}", value as u128)?,
_ => bug!("unsigned ConstInt 0x{value:x} of size {size}"),
}
if fmt.alternate() {
match uty {
UintTy::Usize => write!(fmt, "_usize")?,
UintTy::U8 => write!(fmt, "_u8")?,
UintTy::U16 => write!(fmt, "_u16")?,
UintTy::U32 => write!(fmt, "_u32")?,
UintTy::U64 => write!(fmt, "_u64")?,
UintTy::U128 => write!(fmt, "_u128")?,
}
}
Ok(())
}
Ok(())
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1329,8 +1329,7 @@ pub trait PrettyPrinter<'tcx>:
}
// Int
ty::Uint(_) | ty::Int(_) => {
let int =
ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
let int = ConstInt::new(self.tcx(), int.assert_bits(int.size()), ty);
if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
}
// Char
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_mir_transform/src/const_prop_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_middle::mir::{
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
self, ConstInt, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable,
};
use rustc_session::lint;
use rustc_span::{def_id::DefId, Span};
Expand Down Expand Up @@ -579,10 +579,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
match l {
Some(l) => l.to_const_int(),
// Invent a dummy value, the diagnostic ignores it anyway
None => ConstInt::new(
ScalarInt::try_from_uint(1_u8, left_size).unwrap(),
left_ty.is_signed(),
left_ty.is_ptr_sized_integral(),
None => ConstInt::new_with_width(
1,
left_ty,
left_size.bytes() as u32,
),
},
r.to_const_int(),
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_symbol_mangling/src/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
) => {
// The `pretty_print_const` formatting depends on -Zverbose
// flag, so we cannot reuse it here.
let signed = matches!(ct.ty().kind(), ty::Int(_));
write!(
self,
"{:#?}",
ty::ConstInt::new(scalar, signed, ct.ty().is_ptr_sized_integral())
ty::ConstInt::new(self.tcx, scalar.assert_bits(scalar.size()), ct.ty())
)?;
}
_ => self.write_str("_")?,
Expand Down