diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index bf4152d4b8cd5..5a2c6a161381e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -24,10 +24,17 @@ use super::{ use crate::fluent_generated as fluent; /// Directly returns an `Allocation` containing an absolute path representation of the given type. -pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { - let path = crate::util::type_name(tcx, ty); - let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes(), ()); - tcx.mk_const_alloc(alloc) +pub(crate) fn alloc_type_name<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> (ConstAllocation<'tcx>, u64) { + let mut path = crate::util::type_name(tcx, ty).into_bytes(); + let path_len = path.len().try_into().unwrap(); + if !path.contains(&0) { + path.extend(b"\xff\0"); + }; + let alloc = Allocation::from_bytes_byte_aligned_immutable(path, ()); + (tcx.mk_const_alloc(alloc), path_len) } /// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated @@ -43,8 +50,8 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( interp_ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; - let alloc = alloc_type_name(tcx, tp_ty); - ConstValue::Slice { data: alloc, meta: alloc.inner().size().bytes() } + let (alloc, path_len) = alloc_type_name(tcx, tp_ty); + ConstValue::Slice { data: alloc, meta: path_len } } sym::needs_drop => { ensure_monomorphic_enough(tcx, tp_ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index f5d3de7b1b270..b5d3a22403daa 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -1019,11 +1019,16 @@ where &mut self, s: &str, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - let bytes = s.as_bytes(); - let ptr = self.allocate_bytes_dedup(bytes)?; + let ptr = if !s.contains('\0') { + let mut bytes = s.as_bytes().to_owned(); + bytes.extend(b"\xff\0"); + self.allocate_bytes_dedup(&bytes)? + } else { + self.allocate_bytes_dedup(s.as_bytes())? + }; // Create length metadata for the string. - let meta = Scalar::from_target_usize(u64::try_from(bytes.len()).unwrap(), self); + let meta = Scalar::from_target_usize(u64::try_from(s.len()).unwrap(), self); // Get layout for Rust's str type. let layout = self.layout_of(self.tcx.types.str_).unwrap(); 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 eb8e98ec3644d..58f17a8e0b9a5 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -121,9 +121,15 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> let value = match (lit, lit_ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); - let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ()); + let allocation = if !s.contains('\0') { + let mut s = s.as_bytes().to_owned(); + s.extend(b"\xff\0"); + Allocation::from_bytes_byte_aligned_immutable(s, ()) + } else { + Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ()) + }; let allocation = tcx.mk_const_alloc(allocation); - ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() } + ConstValue::Slice { data: allocation, meta: s.len().try_into().unwrap() } } (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs index 7d17b3b67cfa2..5789e1be517b4 100644 --- a/tests/codegen/remap_path_prefix/main.rs +++ b/tests/codegen/remap_path_prefix/main.rs @@ -12,7 +12,7 @@ mod aux_mod; include!("aux_mod.rs"); // Here we check that the expansion of the file!() macro is mapped. -// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant [34 x i8] c"/the/src/remap_path_prefix/main.rs" +// CHECK: @alloc_643660180b5bd639a42b5b1707ce11a5 = private unnamed_addr constant [36 x i8] c"/the/src/remap_path_prefix/main.rs\FF\00" pub static FILE_PATH: &'static str = file!(); fn main() { diff --git a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir index a2bd2bc0d92ab..d8ebca2215a61 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir @@ -33,12 +33,12 @@ ALLOC2 (size: 16, align: 4) { ╾ALLOC4╼ 03 00 00 00 ╾ALLOC5╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -ALLOC4 (size: 3, align: 1) { - 66 6f 6f │ foo +ALLOC4 (size: 5, align: 1) { + 66 6f 6f ff 00 │ foo.. } -ALLOC5 (size: 3, align: 1) { - 62 61 72 │ bar +ALLOC5 (size: 5, align: 1) { + 62 61 72 ff 00 │ bar.. } ALLOC3 (size: 24, align: 4) { @@ -46,14 +46,14 @@ ALLOC3 (size: 24, align: 4) { 0x10 │ ╾ALLOC8╼ 04 00 00 00 │ ╾──╼.... } -ALLOC6 (size: 3, align: 1) { - 6d 65 68 │ meh +ALLOC6 (size: 5, align: 1) { + 6d 65 68 ff 00 │ meh.. } -ALLOC7 (size: 3, align: 1) { - 6d 6f 70 │ mop +ALLOC7 (size: 5, align: 1) { + 6d 6f 70 ff 00 │ mop.. } -ALLOC8 (size: 4, align: 1) { - 6d c3 b6 70 │ m..p +ALLOC8 (size: 6, align: 1) { + 6d c3 b6 70 ff 00 │ m..p.. } diff --git a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir index a431104d08bec..4e63db8bb9aba 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir @@ -36,12 +36,12 @@ ALLOC2 (size: 32, align: 8) { 0x10 │ ╾ALLOC5╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -ALLOC4 (size: 3, align: 1) { - 66 6f 6f │ foo +ALLOC4 (size: 5, align: 1) { + 66 6f 6f ff 00 │ foo.. } -ALLOC5 (size: 3, align: 1) { - 62 61 72 │ bar +ALLOC5 (size: 5, align: 1) { + 62 61 72 ff 00 │ bar.. } ALLOC3 (size: 48, align: 8) { @@ -50,14 +50,14 @@ ALLOC3 (size: 48, align: 8) { 0x20 │ ╾ALLOC8╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -ALLOC6 (size: 3, align: 1) { - 6d 65 68 │ meh +ALLOC6 (size: 5, align: 1) { + 6d 65 68 ff 00 │ meh.. } -ALLOC7 (size: 3, align: 1) { - 6d 6f 70 │ mop +ALLOC7 (size: 5, align: 1) { + 6d 6f 70 ff 00 │ mop.. } -ALLOC8 (size: 4, align: 1) { - 6d c3 b6 70 │ m..p +ALLOC8 (size: 6, align: 1) { + 6d c3 b6 70 ff 00 │ m..p.. } diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 692c24f054451..b500d31b079bd 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -19,12 +19,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use stable_mir::crate_def::CrateDef; -use stable_mir::mir::alloc::GlobalAlloc; -use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef}; -use stable_mir::mir::{Body, TerminatorKind}; -use stable_mir::ty::{Allocation, ConstantKind, RigidTy, TyKind}; -use stable_mir::{CrateItem, CrateItems, ItemKind}; use std::ascii::Char; use std::assert_matches::assert_matches; use std::cmp::{max, min}; @@ -33,6 +27,13 @@ use std::ffi::CStr; use std::io::Write; use std::ops::ControlFlow; +use stable_mir::crate_def::CrateDef; +use stable_mir::mir::alloc::GlobalAlloc; +use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef}; +use stable_mir::mir::{Body, TerminatorKind}; +use stable_mir::ty::{Allocation, ConstantKind, RigidTy, TyKind}; +use stable_mir::{CrateItem, CrateItems, ItemKind}; + const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. @@ -77,11 +78,13 @@ fn check_bar(item: CrateItem) { let alloc_id_0 = alloc.provenance.ptrs[0].1.0; let GlobalAlloc::Memory(allocation) = GlobalAlloc::from(alloc_id_0) else { unreachable!() }; - assert_eq!(allocation.bytes.len(), 3); + assert_eq!(allocation.bytes.len(), 5); assert_eq!(allocation.bytes[0].unwrap(), Char::CapitalB.to_u8()); assert_eq!(allocation.bytes[1].unwrap(), Char::SmallA.to_u8()); assert_eq!(allocation.bytes[2].unwrap(), Char::SmallR.to_u8()); - assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar")); + assert_eq!(allocation.bytes[3].unwrap(), 0xff); + assert_eq!(allocation.bytes[4].unwrap(), Char::Null.to_u8()); + assert_eq!(allocation.raw_bytes().unwrap(), b"Bar\xff\0"); } /// Check the allocation data for static `C_STR`. diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index 9087c1cf45027..41bdc742262ac 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -17,14 +17,15 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; +use std::convert::TryFrom; +use std::io::Write; +use std::ops::ControlFlow; + use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::mono::Instance; use stable_mir::mir::{Body, ConstOperand, Operand, Rvalue, StatementKind, TerminatorKind}; use stable_mir::ty::{ConstantKind, MirConst}; use stable_mir::{CrateDef, CrateItems, ItemKind}; -use std::convert::TryFrom; -use std::io::Write; -use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; @@ -37,17 +38,17 @@ fn test_transform() -> ControlFlow<()> { let target_fn = *get_item(&items, (ItemKind::Fn, "dummy")).unwrap(); let instance = Instance::try_from(target_fn).unwrap(); let body = instance.body().unwrap(); - check_msg(&body, "oops"); + check_msg(&body, b"oops\xff\0"); let new_msg = "new panic message"; let new_body = change_panic_msg(body, new_msg); - check_msg(&new_body, new_msg); + check_msg(&new_body, new_msg.as_bytes()); ControlFlow::Continue(()) } /// Check that the body panic message matches the given message. -fn check_msg(body: &Body, expected: &str) { +fn check_msg(body: &Body, expected: &[u8]) { let msg = body .blocks .iter() @@ -80,7 +81,7 @@ fn check_msg(body: &Body, expected: &str) { unreachable!() }; let bytes = val.raw_bytes().unwrap(); - Some(std::str::from_utf8(&bytes).unwrap().to_string()) + Some(bytes.to_owned()) } _ => None, })