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 slice::from_raw_parts #67456

Open
2 of 4 tasks
DutchGhost opened this issue Dec 20, 2019 · 17 comments
Open
2 of 4 tasks

Tracking issue for const slice::from_raw_parts #67456

DutchGhost opened this issue Dec 20, 2019 · 17 comments
Labels
A-const-eval Area: constant evaluation (mir interpretation) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-raw-pointers Area: raw pointers, MaybeUninit, NonNull A-slice Area: [T] B-unstable Feature: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. Libs-Small Libs issues that are considered "small" or self-contained Libs-Tracked Libs issues that are tracked on the team's project board. S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@DutchGhost
Copy link
Contributor

DutchGhost commented Dec 20, 2019

Make slice::from_raw_parts and slice::from_raw_parts_mut a const fn available under a feature flag.
This would require a change in the ptr module as well, as slice module just forwards to it.

slice::from_raw_parts[mut] is used in alot of places (e.g slice::from_ref[mut], which would get one step closer into constification if slice::from_raw_parts[mut] is a const fn.

Here is a little playground to show it's possible:
https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=dd5c506a3e082c619f557d972e9956ff

In order to get this working, the following functions and functionalities need to be constified:


Implementation PR for ptr::slice_from_raw_parts: #67462


// core::ptr
pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T];
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T];

// core::slice
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T];
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T];

// core::ptr::NonNull
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self
Centril added a commit to Centril/rust that referenced this issue Dec 21, 2019
…ts, r=dtolnay

Make ptr::slice_from_raw_parts a const fn available under a feature flag

A first step in the direction of rust-lang#67456 .
This makes `ptr::slice_from_raw_parts` and `ptr::slice_from_raw_parts_mut` available as a const fn under a feature flag.
@Centril Centril added T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. A-const-eval Area: constant evaluation (mir interpretation) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. labels Dec 21, 2019
Centril added a commit to Centril/rust that referenced this issue Dec 21, 2019
…ts, r=dtolnay

Make ptr::slice_from_raw_parts a const fn available under a feature flag

A first step in the direction of rust-lang#67456 .
This makes `ptr::slice_from_raw_parts` and `ptr::slice_from_raw_parts_mut` available as a const fn under a feature flag.
@SimonSapin SimonSapin changed the title feature request: const slice::from_raw_parts Tracking issue for const slice::from_raw_parts Jan 21, 2020
@DoumanAsh
Copy link

DoumanAsh commented Apr 22, 2020

Is there particular reason why it remains gated by feature flag instead of just being const fn as it is?

@DutchGhost
Copy link
Contributor Author

DutchGhost commented Apr 23, 2020

Is there particular reason why it remains gated by feature flag instead of just being const fn as it is?

The constant versions of function's and methods in libcore/libstd need a period of time under a feature flag before they can be stabilized as a const function/method. Const functions are 'relatively' new, and the ability of what one can do inside isn't fully determined yet I think.
One of those abilities is how to handle raw pointers, which slice::from_raw_parts[mut] needs.

@josephlr
Copy link
Contributor

@DutchGhost would it make sense for the slice::{from_raw_parts[_mut], from_ref, from_mut} to be constified behind this feature as well? The only thing that seems blocking that is this debug_assert which calls is_aligned_and_not_null.

Checking the alignment will need support from the MIR interpreter, see #62420

@KodrAus KodrAus added A-slice Area: [T] B-unstable Feature: Implemented in the nightly compiler and unstable. Libs-Small Libs issues that are considered "small" or self-contained Libs-Tracked Libs issues that are tracked on the team's project board. A-raw-pointers Area: raw pointers, MaybeUninit, NonNull labels Jul 29, 2020
@DutchGhost
Copy link
Contributor Author

DutchGhost commented Dec 5, 2020

@DutchGhost would it make sense for the slice::{from_raw_parts[_mut], from_ref, from_mut} to be constified behind this feature as well? The only thing that seems blocking that is this debug_assert which calls is_aligned_and_not_null.

Checking the alignment will need support from the MIR interpreter, see #62420

I'd say this indeed should fall under the same feature, as you wouldnt want to have 2 seperate features you need to track for really just one thing. Also I think once #79684 has landed, having a const slice::from_raw_parts is possible!!

@mbartlett21
Copy link
Contributor

Cc. #57563

@DutchGhost
Copy link
Contributor Author

This can now be implemented it seems. But Im not sure whether its decided yet what the plan is on allowing to cast pointers to usizes in const contexts, which is needed for is_aligned_and_not_null:

#![feature(const_ptr_is_null)]
#![feature(const_raw_ptr_to_usize_cast)]
#![feature(const_raw_ptr_deref)]
#![feature(const_slice_from_raw_parts)]
#![feature(const_panic)]


mod slice {
    use core::mem;
    use core::ptr;
    
    pub(crate) const unsafe fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
        !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
    }

    pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
        debug_assert!(
            is_aligned_and_not_null(data),
            "attempt to create unaligned or null slice"
        );
        debug_assert!(
            mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
            "attempt to create slice covering at least half the address space"
        );
        // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
        unsafe { &*ptr::slice_from_raw_parts(data, len) }
    }
    
    pub const fn from_ref<T>(reference: &T) -> &[T] {
        unsafe {
            from_raw_parts(reference, 1)
        }
    }
}

const X: &[usize] = slice::from_ref(&1);

fn main() {
    dbg!(X);
}

@mbartlett21
Copy link
Contributor

@DutchGhost
You can type ptr as usize, but as soon as you try that in const-eval, you get a compiler error:

error: any use of this value will cause an error
  --> src/main.rs:13:27
   |
13 |         !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
   |                           ^^^^^^^^^^^^
   |                           |
   |                           "pointer-to-integer cast" needs an rfc before being allowed inside constants
   |                           inside `is_aligned_and_not_null::<usize>` at src/main.rs:13:27
   |                           inside `slice::from_raw_parts::<usize>` at src/main.rs:18:13
   |                           inside `slice::from_ref::<usize>` at src/main.rs:31:13
   |                           inside `X` at src/main.rs:36:21
...
36 | const X: &[usize] = slice::from_ref(&1);
   | ----------------------------------------
   |
   = note: `#[deny(const_err)]` on by default

(playground)

@DutchGhost

This comment has been minimized.

@WaffleLapkin
Copy link
Member

WaffleLapkin commented Oct 30, 2021

To clarify: this issue is currently tracking the following APIs being const:

// core::ptr
pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T];
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T];

// core::slice
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T];
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T];

The former two methods were implemented in #67462 and the latter two were implemented in #90377.

slice::from_{ref,mut} mentioned in the issue text as a const fn is tracked in #90206.

@tobz
Copy link

tobz commented Mar 11, 2022

As an interested party: is there a path to eventual stabilization here, at least for some of the incremental work that is required? For example, std::ptr::slice_from_raw_parts has been available as a const fn (behind a feature flag) for over 2 years now... but I can't seem to find any actionable comments that provide a reason for it to not be stabilized.

Happy to try and learn/help to get it over the line. 🙏🏻

@WaffleLapkin
Copy link
Member

I think that these API are ready for stabilization 🤔

APIs that return &mut/*mut are probably blocked on #57349, but the &/*const versions can be stabilized and only need https://github.com/orgs/rust-lang/teams/wg-const-eval FCP

@joshtriplett
Copy link
Member

Partial stabilization in FCP at #97522

@joshtriplett
Copy link
Member

The remainder is blocked on #57349.

@joshtriplett joshtriplett added the S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. label Jun 29, 2022
@the8472
Copy link
Member

the8472 commented Mar 20, 2023

I updated the issue description to list the methods in question and added NonNull::slice_from_raw_parts since #97506 changes the tracking issue to this one too.

Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Mar 27, 2023
…rom-raw-parts, r=m-ou-se,the8472

Stabilize `nonnull_slice_from_raw_parts`

FCP is done: rust-lang#71941 (comment)
Note that this doesn't const-stabilize `NonNull::slice_from_raw_parts` as `slice_from_raw_parts_mut` isn't const-stabilized yet. Given rust-lang#67456 and rust-lang#57349, it's not likely available soon, meanwhile, stabilizing only the feature makes some sense, I think.

Closes rust-lang#71941
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 27, 2023
…rom-raw-parts, r=m-ou-se,the8472

Stabilize `nonnull_slice_from_raw_parts`

FCP is done: rust-lang#71941 (comment)
Note that this doesn't const-stabilize `NonNull::slice_from_raw_parts` as `slice_from_raw_parts_mut` isn't const-stabilized yet. Given rust-lang#67456 and rust-lang#57349, it's not likely available soon, meanwhile, stabilizing only the feature makes some sense, I think.

Closes rust-lang#71941
@eduardosm
Copy link
Contributor

Why is this blocked on #57349? Is there any issue about using raw mutable pointers in const fns?

ptr::slice_from_raw_parts_mut can be currently emulated with ptr::slice_from_raw_parts(..).cast_mut() anyways.

@WaffleLapkin
Copy link
Member

@eduardosm I don't think using ptr::slice_from_raw_parts(..).cast_mut() it actually useful. Since you can't get &mut or any other pointer with provenance that allows writing, ptr::slice_from_raw_parts will always return a pointer via which you cannot write. So while cast_mut() returns a *mut, you can't actually use it mutably.

@eduardosm
Copy link
Contributor

I am actually interested in NonNull::slice_from_raw_parts rather than ptr::slice_from_raw_parts_mut. I gave that example because the former is implemented on top of the later, so:

  • ptr::slice_from_raw_parts_mut can be emulated with ptr::slice_from_raw_parts(..).cast_mut(), with questionable usefulness.
  • NonNull::slice_from_raw_parts can be emulated with NonNull::new_unchecked(ptr::slice_from_raw_parts(data.as_ptr(), len).cast_mut()), which is useful for immutable access (but it requires an unsafe block, unlike NonNull::slice_from_raw_parts).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: constant evaluation (mir interpretation) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-raw-pointers Area: raw pointers, MaybeUninit, NonNull A-slice Area: [T] B-unstable Feature: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. Libs-Small Libs issues that are considered "small" or self-contained Libs-Tracked Libs issues that are tracked on the team's project board. S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests