Skip to content

str: Stabilize round_char_boundary feature #145756

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(allocator_api)]
Expand All @@ -51,7 +52,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(ptr_alignment_type)]
#![feature(round_char_boundary)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't you need to cfg_attr(bootstrap, …) the feature in the compiler itself (two instances)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to do this in Clippy's clippy_lints crate as well, since it can now be built by the stage0 compiler.

Copy link
Contributor Author

@okaneco okaneco Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I haven't stabilized a feature that touched these other parts of the compiler before.

I manually reordered the cfg_attr features because tidy check complained about alphabetic ordering, but it didn't suggest what line to place it. I couldn't find an automatic --fix option either. Running ./x fmt didn't seem to adjust it either but maybe I have the setup configured wrong (I have it set to the library contributing mode, not sure if that changes anything).

Copy link
Member

@samueltardieu samueltardieu Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x fmt doesn't reorder AFAICT, you have to put the inner attributes in order by hand (as you did).

Clippy using stage 0 is new and doesn't care about inner attributes order, what you did (order by feature name) is fine as well there.

#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(sized_hierarchy)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
Expand All @@ -26,7 +27,6 @@
#![feature(map_try_insert)]
#![feature(negative_impls)]
#![feature(read_buf)]
#![feature(round_char_boundary)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
Expand Down
1 change: 0 additions & 1 deletion library/alloctests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(round_char_boundary)]
#![feature(slice_partition_dedup)]
#![feature(string_from_utf8_lossy_owned)]
#![feature(string_remove_matches)]
Expand Down
8 changes: 4 additions & 4 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,6 @@ impl str {
/// # Examples
///
/// ```
/// #![feature(round_char_boundary)]
/// let s = "❤️🧡💛💚💙💜";
/// assert_eq!(s.len(), 26);
/// assert!(!s.is_char_boundary(13));
Expand All @@ -405,7 +404,8 @@ impl str {
/// assert_eq!(closest, 10);
/// assert_eq!(&s[..closest], "❤️🧡");
/// ```
#[unstable(feature = "round_char_boundary", issue = "93743")]
#[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn floor_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
Expand Down Expand Up @@ -439,7 +439,6 @@ impl str {
/// # Examples
///
/// ```
/// #![feature(round_char_boundary)]
/// let s = "❤️🧡💛💚💙💜";
/// assert_eq!(s.len(), 26);
/// assert!(!s.is_char_boundary(13));
Expand All @@ -448,7 +447,8 @@ impl str {
/// assert_eq!(closest, 14);
/// assert_eq!(&s[..closest], "❤️🧡💛");
/// ```
#[unstable(feature = "round_char_boundary", issue = "93743")]
#[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn ceil_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
Expand Down
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@
all(target_vendor = "fortanix", target_env = "sgx"),
feature(slice_index_methods, coerce_unsized, sgx_platform)
)]
#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))]
#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
//
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/"
Expand All @@ -12,7 +13,6 @@
#![feature(format_args_nl)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(round_char_boundary)]
#![feature(rustc_private)]
#![feature(test)]
#![warn(rustc::internal)]
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#![feature(iter_intersperse)]
#![feature(iter_partition_in_place)]
#![feature(never_type)]
#![feature(round_char_boundary)]
#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![feature(rustc_private)]
#![feature(stmt_expr_attributes)]
#![feature(unwrap_infallible)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(round_char_boundary)]
#![warn(clippy::char_indices_as_byte_indices)]

trait StrExt {
Expand Down
1 change: 0 additions & 1 deletion src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(round_char_boundary)]
#![warn(clippy::char_indices_as_byte_indices)]

trait StrExt {
Expand Down
28 changes: 14 additions & 14 deletions src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error: indexing into a string with a character position where a byte index is expected
--> tests/ui/char_indices_as_byte_indices.rs:13:24
--> tests/ui/char_indices_as_byte_indices.rs:12:24
|
LL | let _ = prim[..idx];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:12:10
--> tests/ui/char_indices_as_byte_indices.rs:11:10
|
LL | for (idx, _) in prim.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
Expand All @@ -19,14 +19,14 @@ LL + for (idx, _) in prim.char_indices() {
|

error: passing a character position to a method that expects a byte index
--> tests/ui/char_indices_as_byte_indices.rs:15:23
--> tests/ui/char_indices_as_byte_indices.rs:14:23
|
LL | prim.split_at(idx);
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:12:10
--> tests/ui/char_indices_as_byte_indices.rs:11:10
|
LL | for (idx, _) in prim.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
Expand All @@ -37,14 +37,14 @@ LL + for (idx, _) in prim.char_indices() {
|

error: passing a character position to a method that expects a byte index
--> tests/ui/char_indices_as_byte_indices.rs:19:49
--> tests/ui/char_indices_as_byte_indices.rs:18:49
|
LL | let _ = prim[..prim.floor_char_boundary(idx)];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:12:10
--> tests/ui/char_indices_as_byte_indices.rs:11:10
|
LL | for (idx, _) in prim.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
Expand All @@ -55,14 +55,14 @@ LL + for (idx, _) in prim.char_indices() {
|

error: indexing into a string with a character position where a byte index is expected
--> tests/ui/char_indices_as_byte_indices.rs:29:24
--> tests/ui/char_indices_as_byte_indices.rs:28:24
|
LL | let _ = prim[..c.0];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:28:9
--> tests/ui/char_indices_as_byte_indices.rs:27:9
|
LL | for c in prim.chars().enumerate() {
| ^ ^^^^^^^^^^^
Expand All @@ -73,14 +73,14 @@ LL + for c in prim.char_indices() {
|

error: passing a character position to a method that expects a byte index
--> tests/ui/char_indices_as_byte_indices.rs:31:23
--> tests/ui/char_indices_as_byte_indices.rs:30:23
|
LL | prim.split_at(c.0);
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:28:9
--> tests/ui/char_indices_as_byte_indices.rs:27:9
|
LL | for c in prim.chars().enumerate() {
| ^ ^^^^^^^^^^^
Expand All @@ -91,14 +91,14 @@ LL + for c in prim.char_indices() {
|

error: indexing into a string with a character position where a byte index is expected
--> tests/ui/char_indices_as_byte_indices.rs:36:26
--> tests/ui/char_indices_as_byte_indices.rs:35:26
|
LL | let _ = string[..idx];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:35:10
--> tests/ui/char_indices_as_byte_indices.rs:34:10
|
LL | for (idx, _) in string.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
Expand All @@ -109,14 +109,14 @@ LL + for (idx, _) in string.char_indices() {
|

error: passing a character position to a method that expects a byte index
--> tests/ui/char_indices_as_byte_indices.rs:38:25
--> tests/ui/char_indices_as_byte_indices.rs:37:25
|
LL | string.split_at(idx);
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
--> tests/ui/char_indices_as_byte_indices.rs:35:10
--> tests/ui/char_indices_as_byte_indices.rs:34:10
|
LL | for (idx, _) in string.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
Expand Down
Loading