From 98be8f7659a67caae28527fd7c37ba23b5d7ad3b Mon Sep 17 00:00:00 2001 From: Lars Schumann Date: Mon, 9 Mar 2026 23:26:14 +0000 Subject: [PATCH 1/2] Fix Vec::const_make_global for 0 capacity and ZST's --- library/alloc/src/vec/mod.rs | 14 ++++++++++++++ library/alloctests/tests/vec.rs | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7796f3b8b2fb3..8fbdb9a394aec 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -898,6 +898,20 @@ impl Vec { where T: Freeze, { + // const_make_global requires the pointer to point to the beginning of a heap allocation, + // which is not the case when `self.capacity()` is 0, which is why we instead return a new slice. + if self.capacity() == 0 { + _ = ManuallyDrop::new(self); + return &[]; + } + + // if `T::IS_ZST`, the pointer we give to `const_make_global` would again not + // point to the start of a heap allocation + if T::IS_ZST { + let me = ManuallyDrop::new(self); + return unsafe { slice::from_raw_parts(NonNull::::dangling().as_ptr(), me.len) }; + } + unsafe { core::intrinsics::const_make_global(self.as_mut_ptr().cast()) }; let me = ManuallyDrop::new(self); unsafe { slice::from_raw_parts(me.as_ptr(), me.len) } diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs index 5ab305f7a5048..db7da0db47d74 100644 --- a/library/alloctests/tests/vec.rs +++ b/library/alloctests/tests/vec.rs @@ -2764,3 +2764,25 @@ fn const_heap() { assert_eq!([1, 2, 4, 8, 16, 32], X); } + +// regression test for issue #153158. `const_make_global` previously assumed `Vec`'s buf +// always has a heap allocation, which lead to compilation errors. +#[test] +fn const_make_global_empty_or_zst_regression() { + const EMPTY_SLICE: &'static [i32] = { + let empty_vec: Vec = Vec::new(); + empty_vec.const_make_global() + }; + + assert_eq!(EMPTY_SLICE, &[]); + + const ZST_SLICE: &'static [()] = { + let mut zst_vec: Vec<()> = Vec::new(); + zst_vec.push(()); + zst_vec.push(()); + zst_vec.push(()); + zst_vec.const_make_global() + }; + + assert_eq!(ZST_SLICE, &[(), (), ()]); +} From 50ee6f9de6b9a97f6193053ad8d77a16b468761f Mon Sep 17 00:00:00 2001 From: Lars Schumann Date: Tue, 10 Mar 2026 00:39:33 +0000 Subject: [PATCH 2/2] combine 0 capacity and ZST cases --- library/alloc/src/vec/mod.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8fbdb9a394aec..4c27a5ce07517 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -898,23 +898,17 @@ impl Vec { where T: Freeze, { - // const_make_global requires the pointer to point to the beginning of a heap allocation, - // which is not the case when `self.capacity()` is 0, which is why we instead return a new slice. - if self.capacity() == 0 { - _ = ManuallyDrop::new(self); - return &[]; - } - - // if `T::IS_ZST`, the pointer we give to `const_make_global` would again not - // point to the start of a heap allocation - if T::IS_ZST { + // `const_make_global` requires the pointer to point to the beginning of a heap allocation, + // which is not the case when `self.capacity()` is 0, or if `T::IS_ZST`, + // which is why we instead return a new slice in this case. + if self.capacity() == 0 || T::IS_ZST { let me = ManuallyDrop::new(self); - return unsafe { slice::from_raw_parts(NonNull::::dangling().as_ptr(), me.len) }; + unsafe { slice::from_raw_parts(NonNull::::dangling().as_ptr(), me.len) } + } else { + unsafe { core::intrinsics::const_make_global(self.as_mut_ptr().cast()) }; + let me = ManuallyDrop::new(self); + unsafe { slice::from_raw_parts(me.as_ptr(), me.len) } } - - unsafe { core::intrinsics::const_make_global(self.as_mut_ptr().cast()) }; - let me = ManuallyDrop::new(self); - unsafe { slice::from_raw_parts(me.as_ptr(), me.len) } } }