From b0ae21860621da0f2efd6c08dc1f8af7ab2fee55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82uszak?= Date: Wed, 11 Oct 2023 15:12:06 +0200 Subject: [PATCH] Fix #116631 --- compiler/rustc_ast/src/ast.rs | 20 ++++++++++++++++++++ compiler/rustc_ast_lowering/src/format.rs | 8 ++++++-- tests/ui/fmt/issue-116631.rs | 3 +++ tests/ui/fmt/issue-116631.stderr | 11 +++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/ui/fmt/issue-116631.rs create mode 100644 tests/ui/fmt/issue-116631.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e8cbd7b69fbe0..af1c4766177e8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1795,6 +1795,26 @@ pub enum LitIntType { Unsuffixed, } +impl LitIntType { + pub const fn max_literal_value(&self) -> u128 { + match self { + LitIntType::Signed(IntTy::I8) => i8::MAX as u128, + LitIntType::Signed(IntTy::I16) => i16::MAX as u128, + LitIntType::Signed(IntTy::I32) => i32::MAX as u128, + LitIntType::Signed(IntTy::I64) => i64::MAX as u128, + LitIntType::Signed(IntTy::I128) => i128::MAX as u128, + LitIntType::Signed(IntTy::Isize) => isize::MAX as u128, + LitIntType::Unsigned(UintTy::U8) => u8::MAX as u128, + LitIntType::Unsigned(UintTy::U16) => u16::MAX as u128, + LitIntType::Unsigned(UintTy::U32) => u32::MAX as u128, + LitIntType::Unsigned(UintTy::U64) => u64::MAX as u128, + LitIntType::Unsigned(UintTy::U128) => u128::MAX, + LitIntType::Unsigned(UintTy::Usize) => usize::MAX as u128, + LitIntType::Unsuffixed => u128::MAX, + } + } +} + /// Type of the float literal based on provided suffix. #[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)] #[derive(HashStable_Generic)] diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 45a9bebfcf627..410858a2f19c4 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -128,9 +128,13 @@ fn inline_literals(mut fmt: Cow<'_, FormatArgs>) -> Cow<'_, FormatArgs> { { literal = Some(s); } else if let token::LitKind::Integer = lit.kind - && let Ok(LitKind::Int(n, _)) = LitKind::from_token_lit(lit) + && let Ok(LitKind::Int(n, ty)) = LitKind::from_token_lit(lit) { - literal = Some(Symbol::intern(&n.to_string())); + // Check if n fits in the type of the argument. If it doesn't, + // simply don't inline the literal here, the error will be emitted at a later stage. + if n <= ty.max_literal_value() { + literal = Some(Symbol::intern(&n.to_string())); + } } } diff --git a/tests/ui/fmt/issue-116631.rs b/tests/ui/fmt/issue-116631.rs new file mode 100644 index 0000000000000..fb8fc50ab8d56 --- /dev/null +++ b/tests/ui/fmt/issue-116631.rs @@ -0,0 +1,3 @@ +fn main() { + format_args!("{}\n", 0xffff_ffff_u8); //~ ERROR literal out of range for `u8` +} diff --git a/tests/ui/fmt/issue-116631.stderr b/tests/ui/fmt/issue-116631.stderr new file mode 100644 index 0000000000000..dafbca6acd187 --- /dev/null +++ b/tests/ui/fmt/issue-116631.stderr @@ -0,0 +1,11 @@ +error: literal out of range for `u8` + --> $DIR/issue-116631.rs:2:26 + | +LL | format_args!("{}\n", 0xffff_ffff_u8); + | ^^^^^^^^^^^^^^ help: consider using the type `u32` instead: `0xffff_ffff_u32` + | + = note: the literal `0xffff_ffff_u8` (decimal `4294967295`) does not fit into the type `u8` and will become `255u8` + = note: `#[deny(overflowing_literals)]` on by default + +error: aborting due to previous error +