Skip to content

Const evaluation #452

Open
Open
@bjorn3

Description

@bjorn3

@philberty you are planning to use gcc's const folding for constant evaluation, right? How will this handle arbitrarily complex code like this:

// This feature gate is only used within from_bytes_with_nul_unchecked.
// The same point stands with from_bytes_with_nul returning a unit and removing from_bytes_with_nul_unchecked.
#![feature(const_raw_ptr_deref)]

struct CStr([u8]);

enum CStrConvertError {
    NotNulTerminated,
    InteriorNul,
}

impl CStr {
    pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, CStrConvertError> {
        if bytes.is_empty() {
            return Err(CStrConvertError::NotNulTerminated);
        }
        if bytes[bytes.len() - 1] != 0 {
            return Err(CStrConvertError::NotNulTerminated);
        }
        let mut i = 0;
        // `i + 1 < bytes.len()` allows LLVM to optimize away bounds checking,
        // while it couldn't optimize away bounds checks for `i < bytes.len() - 1`.
        while i + 1 < bytes.len() {
            if bytes[i] == 0 {
                return Err(CStrConvertError::InteriorNul);
            }
            i += 1;
        }
        // SAFETY: We just checked that all properties hold.
        Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
    }
    
    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
        // Note: This can be done using pointer deref (which requires
        // `const_raw_ptr_deref` to be const) or `transmute` (which requires
        // `const_transmute` to be const) or `ptr::from_raw_parts` (which
        // requires `ptr_metadata`).
        // While none of them are current stable, it is very likely that one of
        // them will eventually be.
        &*(bytes as *const [u8] as *const Self)
    }
}

(adapted from Rust-for-Linux/linux#273)

I would expect gcc's const folding to not be able to handle at least the while loop here.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions