Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ pub struct Box<
#[rustc_no_mir_inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[cfg(not(no_global_oom_handling))]
fn box_new_uninit(layout: Layout) -> *mut u8 {
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
const fn box_new_uninit(layout: Layout) -> *mut u8 {
match Global.allocate(layout) {
Ok(ptr) => ptr.as_mut_ptr(),
Err(_) => handle_alloc_error(layout),
Expand All @@ -258,10 +259,11 @@ fn box_new_uninit(layout: Layout) -> *mut u8 {
/// This is unsafe, but has to be marked as safe or else we couldn't use it in `vec!`.
#[doc(hidden)]
#[unstable(feature = "liballoc_internals", issue = "none")]
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[inline(always)]
#[cfg(not(no_global_oom_handling))]
#[rustc_diagnostic_item = "box_assume_init_into_vec_unsafe"]
pub fn box_assume_init_into_vec_unsafe<T, const N: usize>(
pub const fn box_assume_init_into_vec_unsafe<T, const N: usize>(
b: Box<MaybeUninit<[T; N]>>,
) -> crate::vec::Vec<T> {
unsafe { (b.assume_init() as Box<[T]>).into_vec() }
Expand Down Expand Up @@ -307,10 +309,11 @@ impl<T> Box<T> {
/// ```
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "new_uninit", since = "1.82.0")]
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[must_use]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
pub const fn new_uninit() -> Box<mem::MaybeUninit<T>> {
// This is the same as `Self::new_uninit_in(Global)`, but manually inlined (just like
// `Box::new`).

Expand Down Expand Up @@ -1197,8 +1200,9 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
/// assert_eq!(*five, 5)
/// ```
#[stable(feature = "new_uninit", since = "1.82.0")]
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[inline(always)]
pub unsafe fn assume_init(self) -> Box<T, A> {
pub const unsafe fn assume_init(self) -> Box<T, A> {
// This is used in the `vec!` macro, so we optimize for minimal IR generation
// even in debug builds.
// SAFETY: `Box<T>` and `Box<MaybeUninit<T>>` have the same layout.
Expand Down Expand Up @@ -1668,8 +1672,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// [memory layout]: self#memory-layout
#[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[inline]
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
let mut b = mem::ManuallyDrop::new(b);
// We carefully get the raw pointer out in a way that Miri's aliasing model understands what
// is happening: using the primitive "deref" of `Box`. In case `A` is *not* `Global`, we
Expand Down
3 changes: 2 additions & 1 deletion library/alloc/src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,9 @@ impl<T> [T] {
/// ```
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[inline]
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
pub const fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
unsafe {
let len = self.len();
let (b, alloc) = Box::into_raw_with_allocator(self);
Expand Down
1 change: 1 addition & 0 deletions library/alloctests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#![feature(binary_heap_pop_if)]
#![feature(casefold)]
#![feature(const_btree_len)]
#![feature(const_cmp)]
#![feature(const_heap)]
#![feature(const_trait_impl)]
#![feature(core_intrinsics)]
Expand Down
23 changes: 23 additions & 0 deletions library/alloctests/tests/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2807,3 +2807,26 @@ fn const_make_global_empty_or_zst_regression() {

assert_eq!(ZST_SLICE, &[(), (), ()]);
}

#[test]
fn const_heap_vec_macro() {
const X: &'static [u32] = {
let x: Vec<u32> = vec![];
assert!(x == []);
x.const_make_global()
};

const Y: &'static [u32] = {
let y: Vec<u32> = vec![1, 2, 3];
assert!(y == [1, 2, 3]);
y.const_make_global()
};

// This arm isn't const yet.
// const Z: &'static [u32] = {
// vec![4; 2].const_make_global()
// };

assert_eq!(X, []);
assert_eq!(Y, [1, 2, 3]);
}
7 changes: 0 additions & 7 deletions tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs

This file was deleted.

21 changes: 0 additions & 21 deletions tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr

This file was deleted.

23 changes: 9 additions & 14 deletions tests/ui/statics/check-values-constraints.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Verifies all possible restrictions for statics values.

#![feature(const_heap)]
#![allow(warnings)]

use std::marker;
Expand Down Expand Up @@ -79,8 +80,6 @@ static STATIC10: UnsafeStruct = UnsafeStruct;
struct MyOwned;

static STATIC11: Vec<MyOwned> = vec![MyOwned];
//~^ ERROR cannot call non-const function
//~| ERROR cannot call non-const

@oli-obk oli-obk Jul 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep using the vec macro and just fix up the diagnostics. Can even enable the feature

View changes since the review

@Lars-Schumann Lars-Schumann Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, many of these have no more errors now since a Vec of ZSTs doesn't allocate.
If we would rather keep these failure cases, I can make MyOwned non-ZST, or introduce cases with a separate non-ZST type.


static mut STATIC12: UnsafeStruct = UnsafeStruct;

Expand All @@ -93,29 +92,25 @@ static mut STATIC14: SafeStruct = SafeStruct {
};

static STATIC15: &'static [Vec<MyOwned>] = &[
vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
vec![MyOwned],
vec![MyOwned],
];

static STATIC16: (&'static Vec<MyOwned>, &'static Vec<MyOwned>) = (
&vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
&vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
&vec![MyOwned],
&vec![MyOwned],
);

static mut STATIC17: SafeEnum = SafeEnum::Variant1;

static STATIC19: Vec<isize> = vec![3];
//~^ ERROR cannot call non-const function
//~| ERROR cannot call non-const
//~^ ERROR encountered `const_allocate` pointer in final value that was not made global


pub fn main() {
let y = {
static x: Vec<isize> = vec![3]; //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
static x: Vec<isize> = vec![3];
//~^ ERROR encountered `const_allocate` pointer in final value that was not made global
x
//~^ ERROR cannot move out of static
};
Expand Down
148 changes: 12 additions & 136 deletions tests/ui/statics/check-values-constraints.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0493]: destructor of `SafeStruct` cannot be evaluated at compile-time
--> $DIR/check-values-constraints.rs:64:7
--> $DIR/check-values-constraints.rs:65:7
|
LL | ..SafeStruct {
| _______^
Expand All @@ -11,28 +11,8 @@ LL | | }
LL | };
| - value is dropped here

error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:81:33
|
LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
| ^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:81:33
|
LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const method `<str as ToString>::to_string` in statics
--> $DIR/check-values-constraints.rs:92:38
--> $DIR/check-values-constraints.rs:91:38
|
LL | field2: SafeEnum::Variant4("str".to_string()),
| ^^^^^^^^^^^
Expand All @@ -47,128 +27,24 @@ note: method `to_string` is not const because trait `ToString` is not const
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:96:5
|
LL | vec![MyOwned],
| ^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:96:5
|
LL | vec![MyOwned],
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:98:5
|
LL | vec![MyOwned],
| ^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:98:5
|
LL | vec![MyOwned],
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:103:6
|
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:103:6
|
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:105:6
|
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:105:6
|
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const associated function `Box::<[isize; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:111:31
error: encountered `const_allocate` pointer in final value that was not made global
--> $DIR/check-values-constraints.rs:106:1
|
LL | static STATIC19: Vec<isize> = vec![3];
| ^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<isize, 1>` in statics
--> $DIR/check-values-constraints.rs:111:31
|
LL | static STATIC19: Vec<isize> = vec![3];
| ^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
= note: use `const_make_global` to turn allocated pointers into immutable globals before returning

error[E0015]: cannot call non-const associated function `Box::<[isize; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:117:32
error: encountered `const_allocate` pointer in final value that was not made global
--> $DIR/check-values-constraints.rs:112:9
|
LL | static x: Vec<isize> = vec![3];
| ^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<isize, 1>` in statics
--> $DIR/check-values-constraints.rs:117:32
|
LL | static x: Vec<isize> = vec![3];
| ^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
= note: use `const_make_global` to turn allocated pointers into immutable globals before returning

error[E0507]: cannot move out of static item `x`
--> $DIR/check-values-constraints.rs:119:9
--> $DIR/check-values-constraints.rs:114:9
|
LL | x
| ^ move occurs because `x` has type `Vec<isize>`, which does not implement the `Copy` trait
Expand All @@ -182,7 +58,7 @@ help: consider cloning the value if the performance cost is acceptable
LL | x.clone()
| ++++++++

error: aborting due to 17 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0015, E0493, E0507.
For more information about an error, try `rustc --explain E0015`.
Loading