Change:
I noticed this check: and wondered why it's there. Then someone told me it's there because of the . If you pass a non-ASCII char, the would corrupt that char. That's why the check is there before it. But then I wondered: why isn't this just cast to a bigger data type that includes all Unicode code points? This method (and others) are slower than they have to be. Also see this discussion in Discord with more valuable information:
(I can’t seem to find the relevant part in the middle of this discord stream…) I’m not sure what you mean by “corrupt”. is well defined: it takes the numerical value of the code point (same as ), then truncates to keep the lower 8 bits. equals 0x41, but so does . We want to reject the latter since U+1F041 is not an ASCII upper-case letter. If is implemented in terms of , the ASCII range check is necessary. (It could be a range check to, for example with .) But maybe doesn’t need to be implemented in terms of . Maybe it could duplicate the logic instead. Once upon a time was implemented with a lookup table of 256 entries. A flat lookup table for all of Unicode would be way too big. But these days it’s based on matching a range pattern. Doing the same with a range pattern could also work. That said, would it actually be faster? Maybe the optimizer already does its job well. If you want to work on this, consider adding some benchmark to show that code duplication is worth it.
Oh it seems the Discord link is a bit buggy. Try searching for in the search bar on the Discord server. Then you should get to my message with the discussion below it. One guy also posted this comparison of the instructions generated:
I think the minimal standard here should be a benchmark before we change the implementation. Can you provide that?
I'm not that experienced with Rust yet, sorry. I just wanted to point out this possible performance regression. Shouldn't the instruction amount difference as shown on Godbolt suffice to know that it's slower? vs.
Looking at the assembly, it seems that the problem is the check. These three functions produce : So, it seems that the check is unnecessary. I could make a PR for this.
Here are some benchmarks: So it seems that removing the check has a measurable performance difference.
is incorrect. The conversion should happen not for the ASCII check but for the , and the pattern use byte literals like . (Though I expect this won’t affect results much.)

Discussion:
#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_alphabetic(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_alphabetic() </del> <ins> match *self { 'A'..='Z' | 'a'..='z' => true, _ => false, } </ins> } /// Checks if the value is an ASCII uppercase character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_uppercase(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_uppercase() </del> <ins> match *self { 'A'..='Z' => true, _ => false, } </ins> } /// Checks if the value is an ASCII lowercase character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_lowercase(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_lowercase() </del> <ins> match *self { 'a'..='z' => true, _ => false, } </ins> } /// Checks if the value is an ASCII alphanumeric character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_alphanumeric(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_alphanumeric() </del> <ins> match *self { '0'..='9' | 'A'..='Z' | 'a'..='z' => true, _ => false, } </ins> } /// Checks if the value is an ASCII decimal digit:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_digit(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_digit() </del> <ins> match *self { '0'..='9' => true, _ => false, } </ins> } /// Checks if the value is an ASCII hexadecimal digit:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_hexdigit(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_hexdigit() </del> <ins> match *self { '0'..='9' | 'A'..='F' | 'a'..='f' => true, _ => false, } </ins> } /// Checks if the value is an ASCII punctuation character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_punctuation(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_punctuation() </del> <ins> match *self { '!'..='/' | ':'..='@' | '['..='`' | '{'..='~' => true, _ => false, } </ins> } /// Checks if the value is an ASCII graphic character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_graphic(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_graphic() </del> <ins> match *self { '!'..='~' => true, _ => false, } </ins> } /// Checks if the value is an ASCII whitespace character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_whitespace(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_whitespace() </del> <ins> match *self { 't' | 'n' | 'x0C' | 'r' | ' ' => true, _ => false, } </ins> } /// Checks if the value is an ASCII control character:

#[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_control(&self) -> bool { <del> self.is_ascii() && (*self as u8).is_ascii_control() </del> <ins> match *self { '0'..='x1F' | 'x7F' => true, _ => false, } </ins> } }