Skip to content

Commit 8d15710

Browse files
Rollup merge of rust-lang#107624 - tgross35:const-cstr-methods, r=dtolnay
Stabilize `const_cstr_methods` This PR seeks to stabilize `const_cstr_methods`. Fixes most of rust-lang#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). rust-lang#107624 (comment) - 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` rust-lang#107624 (comment) cc `@oli-obk` I think you're the const expert `@rustbot` modify labels: +T-libs-api +needs-fcp
2 parents 0a55d79 + 5cb701f commit 8d15710

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

library/core/src/ffi/c_str.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ impl CStr {
241241
/// ```
242242
///
243243
/// ```
244-
/// #![feature(const_cstr_methods)]
244+
/// #![feature(const_cstr_from_ptr)]
245245
///
246246
/// use std::ffi::{c_char, CStr};
247247
///
@@ -256,7 +256,7 @@ impl CStr {
256256
#[inline]
257257
#[must_use]
258258
#[stable(feature = "rust1", since = "1.0.0")]
259-
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
259+
#[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")]
260260
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
261261
// SAFETY: The caller has provided a pointer that points to a valid C
262262
// string with a NUL terminator of size less than `isize::MAX`, whose
@@ -377,7 +377,7 @@ impl CStr {
377377
/// assert!(cstr.is_err());
378378
/// ```
379379
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
380-
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
380+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
381381
pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
382382
let nul_pos = memchr::memchr(0, bytes);
383383
match nul_pos {
@@ -561,10 +561,12 @@ impl CStr {
561561
#[must_use = "this returns the result of the operation, \
562562
without modifying the original"]
563563
#[stable(feature = "rust1", since = "1.0.0")]
564-
pub fn to_bytes(&self) -> &[u8] {
564+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
565+
pub const fn to_bytes(&self) -> &[u8] {
565566
let bytes = self.to_bytes_with_nul();
567+
// FIXME(const-hack) replace with range index
566568
// SAFETY: to_bytes_with_nul returns slice with length at least 1
567-
unsafe { bytes.get_unchecked(..bytes.len() - 1) }
569+
unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
568570
}
569571

570572
/// Converts this C string to a byte slice containing the trailing 0 byte.
@@ -588,7 +590,7 @@ impl CStr {
588590
#[must_use = "this returns the result of the operation, \
589591
without modifying the original"]
590592
#[stable(feature = "rust1", since = "1.0.0")]
591-
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
593+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
592594
pub const fn to_bytes_with_nul(&self) -> &[u8] {
593595
// SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
594596
// is safe on all supported targets.
@@ -612,7 +614,8 @@ impl CStr {
612614
/// assert_eq!(cstr.to_str(), Ok("foo"));
613615
/// ```
614616
#[stable(feature = "cstr_to_str", since = "1.4.0")]
615-
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
617+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
618+
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
616619
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
617620
// instead of in `from_ptr()`, it may be worth considering if this should
618621
// be rewritten to do the UTF-8 check inline with the length calculation

library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
#![feature(const_caller_location)]
114114
#![feature(const_cell_into_inner)]
115115
#![feature(const_char_from_u32_unchecked)]
116-
#![feature(const_cstr_methods)]
117116
#![feature(const_discriminant)]
118117
#![feature(const_eval_select)]
119118
#![feature(const_exact_div)]

0 commit comments

Comments
 (0)