diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 23ded42fa6679..59732cdfbea53 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2449,7 +2449,7 @@ extern "rust-intrinsic" { /// const fn compiletime() -> i32 { 2 } /// /// unsafe { - // // ⚠ This code violates the required equivalence of `compiletime` + /// // ⚠ This code violates the required equivalence of `compiletime` /// // and `runtime`. /// const_eval_select((), compiletime, runtime) /// } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 26c51e8403522..cf793996944c7 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -146,6 +146,7 @@ #![feature(const_replace)] #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] +#![feature(const_slice_eq_ignore_ascii_case)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] #![feature(const_slice_index)] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index f3311f76a7f06..5716a16ca0429 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -2,6 +2,7 @@ use crate::ascii; use crate::fmt::{self, Write}; +use crate::intrinsics; use crate::iter; use crate::mem; use crate::ops; @@ -52,10 +53,33 @@ impl [u8] { /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporaries. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_slice_eq_ignore_ascii_case", issue = "none")] #[must_use] #[inline] - pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { - self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { + const fn eq_ignore_ascii_case_ct(a: &[u8], b: &[u8]) -> bool { + a.len() == b.len() && { + let mut i = 0; + while i < a.len() { + if !u8::eq_ignore_ascii_case(&a[i], &b[i]) { + return false; + } + i += 1; + } + true + } + } + fn eq_ignore_ascii_case_rt(a: &[u8], b: &[u8]) -> bool { + a.len() == b.len() && iter::zip(a, b).all(|(a, b)| u8::eq_ignore_ascii_case(a, b)) + } + // SAFETY: both branches compute the same result, the runtime one is just more optimized + unsafe { + intrinsics::const_eval_select( + (self, other), + eq_ignore_ascii_case_ct, + eq_ignore_ascii_case_rt, + ) + } } /// Converts this slice to its ASCII upper case equivalent in-place. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index ef05b25fdd06c..946c8ae8b0a84 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2391,9 +2391,10 @@ impl str { /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_slice_eq_ignore_ascii_case", issue = "none")] #[must_use] #[inline] - pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { + pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool { self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) } diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index f5f2dd0477885..47d924da95daf 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -16,6 +16,19 @@ fn test_is_ascii() { assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii())); } +#[test] +fn test_is_ascii_const() { + const _: () = { + assert!(b"".is_ascii()); + assert!(b"banana\0\x7F".is_ascii()); + assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii()); + + assert!("".is_ascii()); + assert!("banana\0\u{7F}".is_ascii()); + assert!(!"ประเทศไทย中华Việt Nam".is_ascii()); + }; +} + #[test] fn test_to_ascii_uppercase() { assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL"); @@ -112,6 +125,19 @@ fn test_eq_ignore_ascii_case() { } } +#[test] +fn test_eq_ignore_ascii_case_const() { + const _: () = { + assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl")); + assert!(!"Ürl".eq_ignore_ascii_case("ürl")); + // Dotted capital I, Kelvin sign, Sharp S. + assert!("HİKß".eq_ignore_ascii_case("hİKß")); + assert!(!"İ".eq_ignore_ascii_case("i")); + assert!(!"K".eq_ignore_ascii_case("k")); + assert!(!"ß".eq_ignore_ascii_case("s")); + }; +} + #[test] fn inference_works() { let x = "a".to_string(); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 3c49d1705e5ca..85df486c57b53 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -19,6 +19,7 @@ #![feature(const_pointer_is_aligned)] #![feature(const_ptr_as_ref)] #![feature(const_ptr_write)] +#![feature(const_slice_eq_ignore_ascii_case)] #![feature(const_trait_impl)] #![feature(const_likely)] #![feature(const_location_fields)]