Skip to content

Const raw pointer to usize cast allowed in release mode, disallowed in debug mode #80875

Closed

Description

While making a PoC for #67456 it was discovered that the code beblow fails to compile in debug mode (#67456 (comment)), saying that "pointer-to-integer cast needs an rfc before being allowed in constants", while in release mode, the code compiles and runs.
Here's a playground link.

#![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);
}

Here's the error message in debug mode:

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

error: aborting due to previous error; 1 warning emitted

error: could not compile `playground`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-const-evalArea: Constant evaluation (MIR interpretation)A-diagnosticsArea: Messages for errors, warnings, and lintsE-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions