mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 14:07:04 +00:00
Rollup merge of #107624 - tgross35:const-cstr-methods, r=dtolnay
Stabilize `const_cstr_methods` This PR seeks to stabilize `const_cstr_methods`. Fixes most of #101719 ## New const stable API ```rust impl CStr { // depends: memchr pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {...} // depends: const_slice_index pub const fn to_bytes(&self) -> &[u8] {} // depends: pointer casts pub const fn to_bytes_with_nul(&self) -> &[u8] {} // depends: str::from_utf8 pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {} } ``` I don't think any of these methods will have any issue when `CStr` becomes a thin pointer as long as `memchr` is const (which also allows for const `strlen`) . ## Notes - `from_bytes_until_nul` relies on `const_slice_index`, which relies on `const_trait_impls`, and generally this should be avoided. After talking with Oli, it should be OK in this case because we could replace the ranges with pointer tricks if needed (worst case being those feature gates disappear). https://github.com/rust-lang/rust/pull/107624#discussion_r1101468480 - Making `from_ptr` const is deferred because it depends on `const_eval_select`. I have moved this under the new flag `const_cstr_from_ptr` https://github.com/rust-lang/rust/pull/107624#discussion_r1101555239 cc ``@oli-obk`` I think you're the const expert ``@rustbot`` modify labels: +T-libs-api +needs-fcp
This commit is contained in:
commit
016c306ce6
@ -241,7 +241,7 @@ impl CStr {
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_cstr_methods)]
|
||||
/// #![feature(const_cstr_from_ptr)]
|
||||
///
|
||||
/// use std::ffi::{c_char, CStr};
|
||||
///
|
||||
@ -256,7 +256,7 @@ impl CStr {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
|
||||
#[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")]
|
||||
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
|
||||
// SAFETY: The caller has provided a pointer that points to a valid C
|
||||
// string with a NUL terminator of size less than `isize::MAX`, whose
|
||||
@ -377,7 +377,7 @@ impl CStr {
|
||||
/// assert!(cstr.is_err());
|
||||
/// ```
|
||||
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
|
||||
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
|
||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
|
||||
let nul_pos = memchr::memchr(0, bytes);
|
||||
match nul_pos {
|
||||
@ -561,10 +561,12 @@ impl CStr {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn to_bytes(&self) -> &[u8] {
|
||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn to_bytes(&self) -> &[u8] {
|
||||
let bytes = self.to_bytes_with_nul();
|
||||
// FIXME(const-hack) replace with range index
|
||||
// SAFETY: to_bytes_with_nul returns slice with length at least 1
|
||||
unsafe { bytes.get_unchecked(..bytes.len() - 1) }
|
||||
unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
|
||||
}
|
||||
|
||||
/// Converts this C string to a byte slice containing the trailing 0 byte.
|
||||
@ -588,7 +590,7 @@ impl CStr {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
|
||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn to_bytes_with_nul(&self) -> &[u8] {
|
||||
// SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
|
||||
// is safe on all supported targets.
|
||||
@ -612,7 +614,8 @@ impl CStr {
|
||||
/// assert_eq!(cstr.to_str(), Ok("foo"));
|
||||
/// ```
|
||||
#[stable(feature = "cstr_to_str", since = "1.4.0")]
|
||||
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
|
||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
|
||||
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
|
||||
// instead of in `from_ptr()`, it may be worth considering if this should
|
||||
// be rewritten to do the UTF-8 check inline with the length calculation
|
||||
|
@ -113,7 +113,6 @@
|
||||
#![feature(const_caller_location)]
|
||||
#![feature(const_cell_into_inner)]
|
||||
#![feature(const_char_from_u32_unchecked)]
|
||||
#![feature(const_cstr_methods)]
|
||||
#![feature(const_discriminant)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_exact_div)]
|
||||
|
Loading…
Reference in New Issue
Block a user