From a7ce15d361ca3d774981e35c3c03d8dcccf0ed88 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 30 Jan 2025 12:37:40 +0000 Subject: [PATCH 1/2] Don't allow negative unsigned literals --- compiler/rustc_mir_build/src/thir/constant.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 49db522cf0eed..98edd3fea47ec 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -55,7 +55,11 @@ pub(crate) fn lit_to_const<'tcx>( let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } - (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { + (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => { + let scalar_int = trunc(n.get()); + ty::ValTree::from_scalar_int(scalar_int) + } + (ast::LitKind::Int(n, _), ty::Int(_)) => { let scalar_int = trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }); ty::ValTree::from_scalar_int(scalar_int) From 0cd51863ff1d92a904bec6fc854fbf201fb52bdd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 30 Jan 2025 14:34:50 +0000 Subject: [PATCH 2/2] Avoid calling the layout_of query in lit_to_const --- .../src/builder/expr/as_constant.rs | 21 +++++++------- compiler/rustc_mir_build/src/thir/constant.rs | 28 ++++++++++--------- 2 files changed, 26 insertions(+), 23 deletions(-) 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 e4e452aff7553..84c9297e65898 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -105,13 +105,12 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar)); } - let trunc = |n| { - let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { - Ok(layout) => layout.size, - Err(_) => { - tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) - } - }; + let trunc = |n, width: ty::UintTy| { + let width = width + .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) + .bit_width() + .unwrap(); + let width = Size::from_bits(width); trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); @@ -145,9 +144,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(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { - trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }) - } + (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => trunc(n.get(), *ui), + (ast::LitKind::Int(n, _), ty::Int(i)) => trunc( + if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, + i.to_unsigned(), + ), (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 98edd3fea47ec..f303053390c4d 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,4 +1,5 @@ -use rustc_ast as ast; +use rustc_abi::Size; +use rustc_ast::{self as ast}; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::interpret::LitToConstInput; @@ -17,13 +18,12 @@ pub(crate) fn lit_to_const<'tcx>( return ty::Const::new_error(tcx, guar); } - let trunc = |n| { - let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { - Ok(layout) => layout.size, - Err(_) => { - tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) - } - }; + let trunc = |n, width: ty::UintTy| { + let width = width + .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) + .bit_width() + .unwrap(); + let width = Size::from_bits(width); trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); @@ -55,13 +55,15 @@ pub(crate) fn lit_to_const<'tcx>( let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } - (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => { - let scalar_int = trunc(n.get()); + (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => { + let scalar_int = trunc(n.get(), *ui); ty::ValTree::from_scalar_int(scalar_int) } - (ast::LitKind::Int(n, _), ty::Int(_)) => { - let scalar_int = - trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }); + (ast::LitKind::Int(n, _), ty::Int(i)) => { + let scalar_int = trunc( + if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, + i.to_unsigned(), + ); ty::ValTree::from_scalar_int(scalar_int) } (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),