Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking Issue for const_box #92521

Closed
1 of 3 tasks
lilasta opened this issue Jan 3, 2022 · 16 comments · Fixed by #138800
Closed
1 of 3 tasks

Tracking Issue for const_box #92521

lilasta opened this issue Jan 3, 2022 · 16 comments · Fixed by #138800
Labels
A-box Area: Our favorite opsem complication C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-const_trait_impl `#![feature(const_trait_impl)]` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@lilasta
Copy link
Contributor

lilasta commented Jan 3, 2022

Feature gate: #![feature(const_box)]

This is a tracking issue for implementing const Box<T, A> methods.

Public API

impl<T, A: Allocator> Box<T, A> {
    pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self;
    pub const fn allocator(b: &Self) -> &A;
    pub const fn into_pin(boxed: Self) -> Pin<Self>
    where
        A: 'static;
}

Steps / History

Unresolved Questions

  • None
@lilasta lilasta added C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jan 3, 2022
@beepster4096
Copy link
Contributor

beepster4096 commented Jan 17, 2023

The non-ZST allocator issue has been resolved and should be removed from the unresolved questions list.

@lilasta
Copy link
Contributor Author

lilasta commented Jan 18, 2023

Thanks for the information. I've removed it.

@rinarakaki
Copy link

I'm sorry for my shallow understanding, but can't Clone be constified for Box<T> at the same time?

@chorman0773
Copy link
Contributor

Aparently it is possible on stable to Deref Box in a const-fn: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=52526e62eba8e2846bfcc45bdb04f47e

Was this intentional?

@lilasta
Copy link
Contributor Author

lilasta commented Mar 6, 2023

I'm sorry for my shallow understanding, but can't Clone be constified for Box at the same time?

Currently it cannot. Rust's specialization doesn't yet support const-impl enough, so some Copy specializations will cause a compilation error. (Or we have to mark Copy as #[const_trait])
Example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=eab0289f5fc7537133a8df4ac6449323

pub(crate) trait WriteCloneIntoRaw: Sized {
unsafe fn write_clone_into_raw(&self, target: *mut Self);
}
impl<T: Clone> WriteCloneIntoRaw for T {
#[inline]
default unsafe fn write_clone_into_raw(&self, target: *mut Self) {
// Having allocated *first* may allow the optimizer to create
// the cloned value in-place, skipping the local and move.
unsafe { target.write(self.clone()) };
}
}
impl<T: Copy> WriteCloneIntoRaw for T {
#[inline]
unsafe fn write_clone_into_raw(&self, target: *mut Self) {
// We can always copy in-place, without ever involving a local value.
unsafe { target.copy_from_nonoverlapping(self, 1) };
}
}

Aparently it is possible on stable to Deref Box in a const-fn
Was this intentional?

This behavior is not caused by this feature. It can be reproduced in pre-1.58.0. It may be due to the compiler's special DerefMove behavior.

@RalfJung
Copy link
Member

RalfJung commented Sep 8, 2024

This feature has been mostly removed by #110393, and anyway const_heap is still extremely experimental. Do the remaining methods make any sense to keep or should we just scratch this entirely for now?

@lilasta
Copy link
Contributor Author

lilasta commented Sep 9, 2024

@RalfJung I believe there's little point in keeping the remaining methods. Would it be all right if I create a PR for the removal? As for #92523, I also plan to remove const and close it.

@RalfJung
Copy link
Member

RalfJung commented Sep 9, 2024

That makes sense for me -- @rust-lang/wg-const-eval what do you think?

@workingjubilee workingjubilee added the A-box Area: Our favorite opsem complication label Oct 1, 2024
@oxalica
Copy link
Contributor

oxalica commented Mar 21, 2025

The non-ZST allocator issue has been resolved and should be removed from the unresolved questions list.

It seems Box::from_{raw,non_null} are not included here even with less challenges? They do not depend on const traits or custom allocators, and their functionalities is already implementable via a const transmute.
It's officially recommended to use NonNull::dangling() to construct a Box<ZST> if "Box::new cannot be used", while in fact Box::from_raw cannot be used in const context either and we need a less-semantic transmute currently.

playground

struct Zst;

const CONST_ZST: Box<Zst> = unsafe { std::mem::transmute(std::ptr::dangling::<Zst>()) };

fn main() {
    let free_box = CONST_ZST;
    dbg!(&raw const *free_box);
}

@RalfJung
Copy link
Member

Constructing Box in const is generally unsupported, including for ZST. The fact that your code snippet works and does not cause UB is, I think, not a stable guarantee; you are relying on unstable implementation details.

@oxalica
Copy link
Contributor

oxalica commented Mar 22, 2025

Constructing Box in const is generally unsupported, including for ZST. The fact that your code snippet works and does not cause UB is, I think, not a stable guarantee; you are relying on unstable implementation details.

So do you mean it has different requirement of validity (not sure if it's the correct word) for const and non-const context? I'm expecting const context can only be more strict and checked than runtime context, so if a code is guaranteed to be valid at runtime and it compiles at const context, it should be as valid/correct as runtime (excluding the result difference involving floating point calculations). Am I wrong on this?

It's currently explicitly mentioned Box<SizedT> has the same repr as a pointer to SizedT, and ptr::NonNull::dangling "is the recommended way to build it". I think it's a fair derivation to think std::mem::transmute::<*mut Zst, Box<Zst>>(std::ptr::dangling_mut()) is the correct and guaranteed to work. If it's not the case for const context, we probably need to update the docs to mention it.

For zero-sized values, the Box pointer has to be non-null and sufficiently aligned. The recommended way to build a Box to a ZST if Box::new cannot be used is to use ptr::NonNull::dangling.

On top of these basic layout requirements, a Box must point to a valid value of T.

So long as T: Sized, a Box is guaranteed to be represented as a single pointer and is also ABI-compatible with C pointers (i.e. the C type T*)

@RalfJung
Copy link
Member

so if a code is guaranteed to be valid at runtime and it compiles at const context, it should be as valid/correct as runtime

That's definitely not correct; ptr-to-int transmutes (with their current de-facto but not-yet-stable semantics) are an example of that.

@oxalica
Copy link
Contributor

oxalica commented Mar 24, 2025

so if a code is guaranteed to be valid at runtime and it compiles at const context, it should be as valid/correct as runtime

That's definitely not correct; ptr-to-int transmutes (with their current de-facto but not-yet-stable semantics) are an example of that.

ptr-to-int transmutes are rejected now in const-eval so it fails if part.

@RalfJung
Copy link
Member

I don't know what you mean. They do not get rejected. Here's an example:

const C: () = {
    let x = &5;
    let y: usize = unsafe { std::mem::transmute(x) };
};

TaKO8Ki added a commit to TaKO8Ki/rust that referenced this issue Mar 24, 2025
remove remnants of const_box feature

This feature requires major design work, and the few methods it gates currently aren't actually useful. Let's reset to a clean slate so when a design materializes, we can start from scratch.

Closes rust-lang#92521 by removing the feature it tracks.

r? `@oli-obk`
TaKO8Ki added a commit to TaKO8Ki/rust that referenced this issue Mar 24, 2025
remove remnants of const_box feature

This feature requires major design work, and the few methods it gates currently aren't actually useful. Let's reset to a clean slate so when a design materializes, we can start from scratch.

Closes rust-lang#92521 by removing the feature it tracks.

r? ``@oli-obk``
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 24, 2025
remove remnants of const_box feature

This feature requires major design work, and the few methods it gates currently aren't actually useful. Let's reset to a clean slate so when a design materializes, we can start from scratch.

Closes rust-lang#92521 by removing the feature it tracks.

r? ```@oli-obk```
@oxalica
Copy link
Contributor

oxalica commented Mar 24, 2025

I don't know what you mean. They do not get rejected. Here's an example:

const C: () = {
let x = &5;
let y: usize = unsafe { std::mem::transmute(x) };
};

🤦 Okay seems I have some misunderstanding about const-eval and it's not rejected until "used" in some sense.

Back to the original topic, you suggest that unsafe { std::mem::transmute::<*mut Zst, Box<Zst>>(std::ptr::dangling_mut()) } is guaranteed to create a valid Box::new(Zst) at runtime (though not so useful), but there is currently no stable and guaranteed way to initialize a const Z: Box<Zst>. Is this correct?

@RalfJung
Copy link
Member

RalfJung commented Mar 24, 2025 via email

@bors bors closed this as completed in 0c25157 Mar 24, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Mar 24, 2025
Rollup merge of rust-lang#138800 - RalfJung:const_box, r=oli-obk

remove remnants of const_box feature

This feature requires major design work, and the few methods it gates currently aren't actually useful. Let's reset to a clean slate so when a design materializes, we can start from scratch.

Closes rust-lang#92521 by removing the feature it tracks.

r? ````@oli-obk````
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-box Area: Our favorite opsem complication C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-const_trait_impl `#![feature(const_trait_impl)]` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants