diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4ee41bc807243..58996703023ce 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -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), @@ -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( +pub const fn box_assume_init_into_vec_unsafe( b: Box>, ) -> crate::vec::Vec { unsafe { (b.assume_init() as Box<[T]>).into_vec() } @@ -307,10 +309,11 @@ impl Box { /// ``` #[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> { + pub const fn new_uninit() -> Box> { // This is the same as `Self::new_uninit_in(Global)`, but manually inlined (just like // `Box::new`). @@ -1197,8 +1200,9 @@ impl Box, 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 { + pub const unsafe fn assume_init(self) -> Box { // This is used in the `vec!` macro, so we optimize for minimal IR generation // even in debug builds. // SAFETY: `Box` and `Box>` have the same layout. @@ -1668,8 +1672,9 @@ impl Box { /// [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 diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 39e72e383eacb..da9b40c2c3ce0 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -476,8 +476,9 @@ impl [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(self: Box) -> Vec { + pub const fn into_vec(self: Box) -> Vec { unsafe { let len = self.len(); let (b, alloc) = Box::into_raw_with_allocator(self); diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 96dcde71fc071..296d0708a5f0e 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -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)] diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs index fc58e4364fe66..4620a9f373d6c 100644 --- a/library/alloctests/tests/vec.rs +++ b/library/alloctests/tests/vec.rs @@ -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 = vec![]; + assert!(x == []); + x.const_make_global() + }; + + const Y: &'static [u32] = { + let y: Vec = 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]); +} diff --git a/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs index 74e0a36560b08..a906209bc2726 100644 --- a/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs +++ b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs @@ -1,7 +1,10 @@ -const fn foo(a: i32) -> Vec { +fn non_const() -> Vec { vec![1, 2, 3] - //~^ ERROR cannot call non-const - //~| ERROR cannot call non-const +} + +const fn foo(a: i32) -> Vec { + non_const() + //~^ ERROR cannot call non-const function } fn main() {} diff --git a/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr index a7e8fdf37ae29..82ad129c46ec9 100644 --- a/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr +++ b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr @@ -1,21 +1,16 @@ -error[E0015]: cannot call non-const associated function `Box::<[i32; 3]>::new_uninit` in constant functions - --> $DIR/bad_const_fn_body_ice.rs:2:5 +error[E0015]: cannot call non-const function `non_const` in constant functions + --> $DIR/bad_const_fn_body_ice.rs:6:5 | -LL | vec![1, 2, 3] - | ^^^^^^^^^^^^^ +LL | non_const() + | ^^^^^^^^^^^ | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::` in constant functions - --> $DIR/bad_const_fn_body_ice.rs:2:5 - | -LL | vec![1, 2, 3] - | ^^^^^^^^^^^^^ +note: function `non_const` is not const + --> $DIR/bad_const_fn_body_ice.rs:1:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const() -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/statics/check-values-constraints.rs b/tests/ui/statics/check-values-constraints.rs index c62abd75a304b..4263ac46c654f 100644 --- a/tests/ui/statics/check-values-constraints.rs +++ b/tests/ui/statics/check-values-constraints.rs @@ -68,6 +68,10 @@ static STATIC9: SafeStruct = SafeStruct { } }; +fn non_const(value: T) -> Vec { + vec![value] +} + struct UnsafeStruct; impl Drop for UnsafeStruct { @@ -78,9 +82,8 @@ static STATIC10: UnsafeStruct = UnsafeStruct; struct MyOwned; -static STATIC11: Vec = vec![MyOwned]; +static STATIC11: Vec = non_const(MyOwned); //~^ ERROR cannot call non-const function -//~| ERROR cannot call non-const static mut STATIC12: UnsafeStruct = UnsafeStruct; @@ -93,29 +96,23 @@ static mut STATIC14: SafeStruct = SafeStruct { }; static STATIC15: &'static [Vec] = &[ - 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 + non_const(MyOwned), //~ ERROR cannot call non-const function + non_const(MyOwned), //~ ERROR cannot call non-const function ]; static STATIC16: (&'static Vec, &'static Vec) = ( - &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 + &non_const(MyOwned), //~ ERROR cannot call non-const function + &non_const(MyOwned), //~ ERROR cannot call non-const function ); static mut STATIC17: SafeEnum = SafeEnum::Variant1; -static STATIC19: Vec = vec![3]; +static STATIC19: Vec = non_const(3); //~^ ERROR cannot call non-const function -//~| ERROR cannot call non-const pub fn main() { let y = { - static x: Vec = vec![3]; //~ ERROR cannot call non-const function - //~| ERROR cannot call non-const + static x: Vec = non_const(3); //~ ERROR cannot call non-const function x //~^ ERROR cannot move out of static }; diff --git a/tests/ui/statics/check-values-constraints.stderr b/tests/ui/statics/check-values-constraints.stderr index 94d2b8ce80641..ec126131e9339 100644 --- a/tests/ui/statics/check-values-constraints.stderr +++ b/tests/ui/statics/check-values-constraints.stderr @@ -11,28 +11,22 @@ 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 +error[E0015]: cannot call non-const function `non_const::` in statics + --> $DIR/check-values-constraints.rs:85:33 | -LL | static STATIC11: Vec = vec![MyOwned]; - | ^^^^^^^^^^^^^ +LL | static STATIC11: Vec = non_const(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::` in statics - --> $DIR/check-values-constraints.rs:81:33 - | -LL | static STATIC11: Vec = vec![MyOwned]; - | ^^^^^^^^^^^^^ +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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 `::to_string` in statics - --> $DIR/check-values-constraints.rs:92:38 + --> $DIR/check-values-constraints.rs:95:38 | LL | field2: SafeEnum::Variant4("str".to_string()), | ^^^^^^^^^^^ @@ -47,128 +41,92 @@ 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 +error[E0015]: cannot call non-const function `non_const::` in statics + --> $DIR/check-values-constraints.rs:99: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::` in statics - --> $DIR/check-values-constraints.rs:96:5 +LL | non_const(MyOwned), + | ^^^^^^^^^^^^^^^^^^ | -LL | vec![MyOwned], - | ^^^^^^^^^^^^^ +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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 +error[E0015]: cannot call non-const function `non_const::` in statics + --> $DIR/check-values-constraints.rs:100:5 | -LL | vec![MyOwned], - | ^^^^^^^^^^^^^ +LL | non_const(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::` in statics - --> $DIR/check-values-constraints.rs:98:5 - | -LL | vec![MyOwned], - | ^^^^^^^^^^^^^ +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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 +error[E0015]: cannot call non-const function `non_const::` in statics + --> $DIR/check-values-constraints.rs:104:6 | -LL | &vec![MyOwned], - | ^^^^^^^^^^^^^ +LL | &non_const(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::` in statics - --> $DIR/check-values-constraints.rs:103:6 +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -LL | &vec![MyOwned], - | ^^^^^^^^^^^^^ - | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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 +error[E0015]: cannot call non-const function `non_const::` in statics --> $DIR/check-values-constraints.rs:105:6 | -LL | &vec![MyOwned], - | ^^^^^^^^^^^^^ +LL | &non_const(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::` in statics - --> $DIR/check-values-constraints.rs:105:6 - | -LL | &vec![MyOwned], - | ^^^^^^^^^^^^^ +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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 - | -LL | static STATIC19: Vec = vec![3]; - | ^^^^^^^ +error[E0015]: cannot call non-const function `non_const::` in statics + --> $DIR/check-values-constraints.rs:110:31 | - = 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::` in statics - --> $DIR/check-values-constraints.rs:111:31 +LL | static STATIC19: Vec = non_const(3); + | ^^^^^^^^^^^^ | -LL | static STATIC19: Vec = vec![3]; - | ^^^^^^^ +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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:117:32 - | -LL | static x: Vec = vec![3]; - | ^^^^^^^ +error[E0015]: cannot call non-const function `non_const::` in statics + --> $DIR/check-values-constraints.rs:115:32 | - = 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::` in statics - --> $DIR/check-values-constraints.rs:117:32 +LL | static x: Vec = non_const(3); + | ^^^^^^^^^^^^ | -LL | static x: Vec = vec![3]; - | ^^^^^^^ +note: function `non_const` is not const + --> $DIR/check-values-constraints.rs:71:1 | -note: function `box_assume_init_into_vec_unsafe` is not const - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | fn non_const(value: T) -> Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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[E0507]: cannot move out of static item `x` - --> $DIR/check-values-constraints.rs:119:9 + --> $DIR/check-values-constraints.rs:116:9 | LL | x | ^ move occurs because `x` has type `Vec`, which does not implement the `Copy` trait @@ -182,7 +140,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 10 previous errors Some errors have detailed explanations: E0015, E0493, E0507. For more information about an error, try `rustc --explain E0015`.