diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6a86e9af71826..63a81b70e95f8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -19,19 +19,19 @@ //! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators. use std::borrow::{Borrow, Cow}; +use std::fmt::Formatter; use std::{cmp, fmt}; pub use GenericArgs::*; pub use UnsafeSource::*; pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy}; -use rustc_data_structures::packed::Pu128; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, StableHash, Walkable}; pub use rustc_span::AttrId; use rustc_span::{ ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan, - sym, + sym, with_session_globals, }; use thin_vec::{ThinVec, thin_vec}; @@ -2276,7 +2276,7 @@ pub enum LitKind { /// A character literal (`'a'`). Char(char), /// An integer literal (`1`). - Int(Pu128, LitIntType), + Int(CompressedIntLiteral, LitIntType), /// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is /// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq` /// and `Hash`. @@ -2336,6 +2336,69 @@ impl LitKind { } } +const MAX_INLINE_INT_LITERAL_VALUE: u32 = 0b01111111111111111111111111111111; + +/// 128-bit integer literal that is either: +/// - Stored inline, if its value is < 2^31 +/// - Stored as an index into a global interned table, if it is larger. +/// +/// The highest bit of the value is set to 1 if it is interned. +/// +/// The motivation for this optimization is to reduce the size of the LitKind AST node. +#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq, StableHash)] +pub struct CompressedIntLiteral(u32); + +impl CompressedIntLiteral { + pub fn from_u128(value: u128) -> Self { + // Store inline + if value <= MAX_INLINE_INT_LITERAL_VALUE as u128 { + Self(value as u32) + } else { + // Store interned + let index = with_session_globals(|session| { + session.int_literal_interner.with_lock(|interner| interner.intern(value)) + }); + assert!(index <= MAX_INLINE_INT_LITERAL_VALUE); + let index = (1 << 31) | index; + Self(index) + } + } + + #[inline] + pub fn as_u8(&self) -> Result { + self.as_u128().try_into() + } + + #[inline] + pub fn as_u32(&self) -> Result { + self.as_u128().try_into() + } + + #[inline] + pub fn as_u64(&self) -> Result { + self.as_u128().try_into() + } + + #[inline] + pub fn as_u128(&self) -> u128 { + let is_inline = self.0 <= MAX_INLINE_INT_LITERAL_VALUE; + if is_inline { + self.0 as u128 + } else { + let key = self.0 & MAX_INLINE_INT_LITERAL_VALUE; + with_session_globals(|session| { + session.int_literal_interner.with_lock(|interner| interner.get(key)) + }) + } + } +} + +impl std::fmt::Display for CompressedIntLiteral { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + self.as_u128().fmt(f) + } +} + /// Represents a function's signature in a trait declaration, /// trait implementation, or free function. #[derive(Clone, Encodable, Decodable, Debug)] @@ -4480,11 +4543,11 @@ mod size_asserts { static_assert_size!(Item, 144); static_assert_size!(ItemKind, 88); static_assert_size!(Lifetime, 16); - static_assert_size!(LitKind, 24); + static_assert_size!(LitKind, 8); static_assert_size!(Local, 96); - static_assert_size!(MetaItem, 80); - static_assert_size!(MetaItemKind, 40); - static_assert_size!(MetaItemLit, 40); + static_assert_size!(MetaItem, 64); + static_assert_size!(MetaItemKind, 24); + static_assert_size!(MetaItemLit, 24); static_assert_size!(NormalAttr, 80); static_assert_size!(Param, 40); static_assert_size!(Pat, 64); diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index b5d8fc821ae0e..d247a634acded 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -9,6 +9,7 @@ use rustc_literal_escaper::{ use rustc_span::{ByteSymbol, Span, Symbol, kw, sym}; use tracing::debug; +use crate::CompressedIntLiteral; use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; use crate::token::{self, Token}; @@ -363,6 +364,6 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result LoweringContext<'_, 'hir> { match LitKind::from_token_lit(lit) { Ok(LitKind::Str(s, _)) => Some(s), Ok(LitKind::Int(n, ty)) => { + let n = n.as_u128(); match ty { // unsuffixed integer literals are assumed to be i32's LitIntType::Unsuffixed => { diff --git a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs index 111aca58e424c..dc9e2b518bf13 100644 --- a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs +++ b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs @@ -68,7 +68,7 @@ impl SingleAttributeParser for RustcAutodiffParser { let width = if let Some(width) = items.peek() && let MetaItemOrLitParser::Lit(width) = width && let LitKind::Int(width, _) = width.kind - && let Ok(width) = width.0.try_into() + && let Ok(width) = width.as_u32() { _ = items.next(); width diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 2553829f8c5ce..e5cc9a204f2a6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -890,7 +890,7 @@ impl SingleAttributeParser for PatchableFunctionEntryParser { return None; }; - let Ok(val) = val.get().try_into() else { + let Ok(val) = val.as_u8() else { cx.adcx().expected_integer_literal_in_range( value.value_span, u8::MIN as isize, diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index bc4f9d20545fc..e5b6b4e5f42d9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -250,13 +250,12 @@ fn parse_alignment(node: &LitKind, cx: &AcceptContext<'_, '_>) -> Result { diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 21f424836e476..f561a2a779a8e 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -48,7 +48,7 @@ mod llvm_enzyme { match l.kind { ast::LitKind::Int(val, _) => { // get an Ident from a lit - return rustc_span::Ident::from_str(val.get().to_string().as_str()); + return rustc_span::Ident::from_str(val.as_u128().to_string().as_str()); } _ => {} } @@ -66,7 +66,7 @@ mod llvm_enzyme { fn width(x: &MetaItemInner) -> Option { let lit = x.lit()?; match lit.kind { - ast::LitKind::Int(x, _) => Some(x.get()), + ast::LitKind::Int(x, _) => Some(x.as_u128()), _ => None, } } diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 15d0f43d039f2..06537a2f5de76 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -71,7 +71,7 @@ fn invalid_type_err( dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg, cs_note: None }) } Ok(LitKind::Int(val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8))) => { - assert!(val.get() > u8::MAX.into()); // must be an error + assert!(val.as_u128() > u8::MAX.into()); // must be an error dcx.emit_err(ConcatBytesOob { span }) } Ok(LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }), @@ -99,7 +99,7 @@ fn handle_array_element( Ok(LitKind::Int( val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8), - )) if let Ok(val) = u8::try_from(val.get()) => { + )) if let Ok(val) = val.as_u8() => { return Some(val); } Ok(LitKind::Byte(val)) => return Some(val), @@ -165,7 +165,7 @@ pub(crate) fn expand_concat_bytes( if let Some(elem) = handle_array_element(cx, &mut guar, &mut missing_literals, expr) { - for _ in 0..count_val.get() { + for _ in 0..count_val.as_u128() { accumulator.push(elem); } } diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 807d4fae6de15..b1edf557742ba 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -260,7 +260,7 @@ fn parse_depth<'psess>( }; if let Ok(lit_kind) = LitKind::from_token_lit(*lit) && let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind - && let Ok(n_usize) = usize::try_from(n_u128.get()) + && let Ok(n_usize) = usize::try_from(n_u128.as_u128()) { Ok(n_usize) } else { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1e75902884fe1..5a8719583f783 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2015,7 +2015,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) tcx.hir_node_by_def_id(discr_def_id.expect_local()) && let hir::ExprKind::Lit(lit) = &tcx.hir_body(expr.body).value.kind && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node - && *lit_value != dis.val + && lit_value.as_u128() != dis.val { (tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)")) } else { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9f0d00d5274fa..d2fae0efc917d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3476,7 +3476,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If index is an unsuffixed integer, show the fixed expression: if let ExprKind::Lit(lit) = idx.kind && let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node - && i.get() < types.len().try_into().expect("tuple length fits in u128") + && i.as_u128() + < types.len().try_into().expect("tuple length fits in u128") { err.span_suggestion( brackets_span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 937182c2030da..208962a7989e3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1038,7 +1038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match layout.backend_repr { rustc_abi::BackendRepr::Scalar(scalar) => { - scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty) + scalar.valid_range(&tcx).contains(i.as_u128()).then_some(ty) } _ => unreachable!(), } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 116bbf6280642..b1356c68ed46a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -6,7 +6,6 @@ use hir::def_id::LocalDefId; use itertools::Itertools; use rustc_ast::util::parser::ExprPrecedence; use rustc_attr_ir::lang_items::LangItem; -use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan, listify, msg}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -1887,8 +1886,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let (_, suffix) = snippet.split_at(snippet.len() - 3); let value = match suffix { - "f32" => (lit.get() - 0xf32) / (16 * 16 * 16), - "f64" => (lit.get() - 0xf64) / (16 * 16 * 16), + "f32" => (lit.as_u128() - 0xf32) / (16 * 16 * 16), + "f64" => (lit.as_u128() - 0xf64) / (16 * 16 * 16), _ => return false, }; err.span_suggestions( @@ -1918,10 +1917,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Provided expression needs to be a literal `0`. - let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(Pu128(0), _), span }) = expr.kind + let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(int, _), span }) = expr.kind else { return false; }; + if int.as_u128() != 0 { + return false; + } // We need to find a null pointer symbol to suggest let null_sym = match mutbl { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 526f29cb3753b..b518c5de36107 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -1,7 +1,6 @@ //! Code related to processing overloaded binary and unary operators. use rustc_ast::{self as ast, AssignOp, BinOp}; -use rustc_data_structures::packed::Pu128; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; @@ -1032,12 +1031,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Expr { kind: ExprKind::Lit(Spanned { - node: ast::LitKind::Int(Pu128(1), _), + node: ast::LitKind::Int(int, _), .. }), .. }, ) = ex.kind + && int.as_u128() == 1 { let span = if let hir::Node::Expr(parent) = self.tcx.parent_hir_node(ex.hir_id) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2c8c6a3ce7f17..ab50433e8782b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2346,7 +2346,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { match &expr.kind { Lit(lit) => { if let Int(i, _) = lit.node { - i == 0 + i.as_u128() == 0 } else { false } @@ -2674,7 +2674,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { match &expr.kind { hir::ExprKind::Lit(lit) => { if let LitKind::Int(a, _) = lit.node { - return a == 0; + return a.as_u128() == 0; } } _ => {} diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs index 78ee1a3ed606b..f65e655a94cd3 100644 --- a/compiler/rustc_lint/src/invalid_from_utf8.rs +++ b/compiler/rustc_lint/src/invalid_from_utf8.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 { .map(|e| match &e.kind { ExprKind::Lit(Spanned { node: lit, .. }) => match lit { LitKind::Byte(b) => Some(*b), - LitKind::Int(b, _) => Some(b.get() as u8), + LitKind::Int(b, _) => Some(b.as_u128() as u8), _ => None, }, _ => None, diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index c231bd4cc3b30..9ce4426a940c2 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -124,7 +124,7 @@ fn is_null_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option LateLintPass<'tcx> for PtrNullChecks { ExprKind::Cast(cast_expr, _) if let ExprKind::Lit(spanned) = cast_expr.kind && let LitKind::Int(v, _) = spanned.node - && v == 0 => + && v.as_u128() == 0 => { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 3b269a215cb6b..e51c6477437e2 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -156,7 +156,7 @@ fn check_int_to_ptr_transmute<'tcx>( }; // bail-out if the argument is literal 0 as we have other lints for those cases if let hir::ExprKind::Lit(hir::Lit { node: LitKind::Int(v, _), .. }) = arg.kind - && v == 0 + && v.as_u128() == 0 { return; } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 9897e9cbb4f07..d4e509d1495a8 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -669,7 +669,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { ast::LitKind::Int( v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed, - ) => v.get() as i128, + ) => v.as_u128() as i128, _ => return true, }, _ => bug!(), @@ -680,7 +680,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { let (min, max): (u128, u128) = uint_ty_range(uint_ty); let lit_val: u128 = match lit.kind { hir::ExprKind::Lit(li) => match li.node { - ast::LitKind::Int(v, _) => v.get(), + ast::LitKind::Int(v, _) => v.as_u128(), _ => return true, }, _ => bug!(), diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 40681664e4437..44c1503ad68cb 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -336,7 +336,7 @@ fn lint_uint_literal<'tcx>( let lit_val: u128 = match lit.node { // _v is u8, within range by definition ast::LitKind::Byte(_v) => return, - ast::LitKind::Int(v, _) => v.get(), + ast::LitKind::Int(v, _) => v.as_u128(), _ => bug!(), }; @@ -422,7 +422,7 @@ pub(crate) fn lint_literal<'tcx>( ty::Int(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => { - lint_int_literal(cx, hir_id, span, lit, t, v.get(), surrounding_negation) + lint_int_literal(cx, hir_id, span, lit, t, v.as_u128(), surrounding_negation) } _ => bug!(), }; diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 8f2a732acd1c2..be4960ea22002 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -193,11 +193,11 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))) } - (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()), + (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.as_u128()), (ast::LitKind::Int(n, _), ty::Int(_)) => { // Unsigned "negation" has the same bitwise effect as signed negation, // which gets the result we want without additional casts. - trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }) + trunc(if neg { u128::wrapping_neg(n.as_u128()) } else { n.as_u128() }) } (ast::LitKind::Float(n, _), ty::Float(fty)) => { parse_float_into_constval(n, *fty, neg).unwrap() diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index a669e09475232..32d01fd0f7cd6 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -73,24 +73,28 @@ pub(crate) fn lit_to_const<'tcx>( (valtree, valtree_ty) } (ast::LitKind::Int(n, ast::LitIntType::Unsigned(ui)), _) if !neg => { - let scalar_int = trunc(n.get(), ui); + let scalar_int = trunc(n.as_u128(), ui); (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, ui)) } (ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)), _) if neg => return None, (ast::LitKind::Int(n, ast::LitIntType::Signed(i)), _) => { - let scalar_int = - trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned()); + let scalar_int = trunc( + if neg { u128::wrapping_neg(n.as_u128()) } else { n.as_u128() }, + i.to_unsigned(), + ); (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i)) } (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Uint(ui))) if !neg => { - let scalar_int = trunc(n.get(), *ui); + let scalar_int = trunc(n.as_u128(), *ui); (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui)) } (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Int(i))) => { // Unsigned "negation" has the same bitwise effect as signed negation, // which gets the result we want without additional casts. - let scalar_int = - trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned()); + let scalar_int = trunc( + if neg { u128::wrapping_neg(n.as_u128()) } else { n.as_u128() }, + i.to_unsigned(), + ); (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, *i)) } (ast::LitKind::Bool(b), _) => (ty::ValTree::from_scalar_int(tcx, b.into()), tcx.types.bool), diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f5e44d768faa1..9824215127062 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -232,6 +232,7 @@ impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> { }; // Detect literal value out of range `[min, max]` inclusive, avoiding use of `-min` to // prevent overflow/panic. + let lit_val = lit_val.as_u128(); if (negated && lit_val > max + 1) || (!negated && lit_val > max) { return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max })); } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ddec29eca6517..b79499616dd94 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -120,6 +120,8 @@ pub struct SessionGlobals { metavar_spans: MetavarSpansMap, hygiene_data: Lock, + pub int_literal_interner: Lock, + /// The session's source map, if there is one. This field should only be /// used in places where the `Session` is truly not available, such as /// `::fmt`. @@ -137,6 +139,7 @@ impl SessionGlobals { span_interner: Lock::new(span_encoding::SpanInterner::default()), metavar_spans: Default::default(), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), + int_literal_interner: Lock::new(IntLiteralInterner::default()), source_map: sm_inputs.map(|inputs| Arc::new(SourceMap::with_inputs(inputs))), } } @@ -197,6 +200,25 @@ pub fn create_default_session_globals_then(f: impl FnOnce() -> R) -> R { // deserialization. scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals); +#[derive(Default)] +pub struct IntLiteralInterner { + literal_map: UnordMap, +} + +impl IntLiteralInterner { + #[inline] + pub fn intern(&mut self, value: u128) -> u32 { + let index = self.literal_map.len() as u32; + self.literal_map.insert(index, value); + index + } + + #[inline] + pub fn get(&self, key: u32) -> u128 { + *self.literal_map.get(&key).unwrap() + } +} + #[derive(Default)] pub struct MetavarSpansMap(FreezeLock>);