Open
Description
@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
Type
Projects
Status
Todo