about summary refs log tree commit diff
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2021-09-25 23:57:26 +0200
committerest31 <MTest31@outlook.com>2021-10-16 01:20:02 +0200
commit7272b6fc8ce5c5d4b087129029c0a5be2570dd44 (patch)
treed7899704034e36ad2f7f5922a3d84bb3bb7ed52f
parentc1026539bd22e9d070988deaa47b1360cbc76436 (diff)
downloadrust-7272b6fc8ce5c5d4b087129029c0a5be2570dd44.tar.gz
rust-7272b6fc8ce5c5d4b087129029c0a5be2570dd44.zip
Make char conversion functions unstably const
-rw-r--r--library/core/src/char/convert.rs32
-rw-r--r--library/core/src/char/methods.rs15
-rw-r--r--library/core/src/lib.rs1
3 files changed, 33 insertions, 15 deletions
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index 72921414fb3..6e48faba84c 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -51,8 +51,13 @@ use super::MAX;
 #[must_use]
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn from_u32(i: u32) -> Option<char> {
-    char::try_from(i).ok()
+#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
+pub const fn from_u32(i: u32) -> Option<char> {
+    // FIXME: once Result::ok is const fn, use it here
+    match char_try_from_u32(i) {
+        Ok(c) => Some(c),
+        Err(_) => None,
+    }
 }
 
 /// Converts a `u32` to a `char`, ignoring validity.
@@ -91,7 +96,8 @@ pub fn from_u32(i: u32) -> Option<char> {
 #[inline]
 #[must_use]
 #[stable(feature = "char_from_unchecked", since = "1.5.0")]
-pub unsafe fn from_u32_unchecked(i: u32) -> char {
+#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
+pub const unsafe fn from_u32_unchecked(i: u32) -> char {
     // SAFETY: the caller must guarantee that `i` is a valid char value.
     if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
 }
@@ -244,18 +250,23 @@ impl FromStr for char {
     }
 }
 
+#[inline]
+const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
+    if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
+        Err(CharTryFromError(()))
+    } else {
+        // SAFETY: checked that it's a legal unicode value
+        Ok(unsafe { transmute(i) })
+    }
+}
+
 #[stable(feature = "try_from", since = "1.34.0")]
 impl TryFrom<u32> for char {
     type Error = CharTryFromError;
 
     #[inline]
     fn try_from(i: u32) -> Result<Self, Self::Error> {
-        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
-            Err(CharTryFromError(()))
-        } else {
-            // SAFETY: checked that it's a legal unicode value
-            Ok(unsafe { transmute(i) })
-        }
+        char_try_from_u32(i)
     }
 }
 
@@ -323,7 +334,8 @@ impl fmt::Display for CharTryFromError {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn from_digit(num: u32, radix: u32) -> Option<char> {
+#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
+pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
     if radix > 36 {
         panic!("from_digit: radix is too high (maximum 36)");
     }
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 3c4972bd3c9..d5ad0c385c7 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -136,9 +136,10 @@ impl char {
     /// assert_eq!(None, c);
     /// ```
     #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
+    #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
     #[must_use]
     #[inline]
-    pub fn from_u32(i: u32) -> Option<char> {
+    pub const fn from_u32(i: u32) -> Option<char> {
         super::convert::from_u32(i)
     }
 
@@ -178,9 +179,10 @@ impl char {
     /// assert_eq!('❤', c);
     /// ```
     #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
+    #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
     #[must_use]
     #[inline]
-    pub unsafe fn from_u32_unchecked(i: u32) -> char {
+    pub const unsafe fn from_u32_unchecked(i: u32) -> char {
         // SAFETY: the safety contract must be upheld by the caller.
         unsafe { super::convert::from_u32_unchecked(i) }
     }
@@ -235,9 +237,10 @@ impl char {
     /// let _c = char::from_digit(1, 37);
     /// ```
     #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
+    #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
     #[must_use]
     #[inline]
-    pub fn from_digit(num: u32, radix: u32) -> Option<char> {
+    pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
         super::convert::from_digit(num, radix)
     }
 
@@ -331,10 +334,11 @@ impl char {
     /// let _ = '1'.to_digit(37);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
-    pub fn to_digit(self, radix: u32) -> Option<u32> {
+    pub const fn to_digit(self, radix: u32) -> Option<u32> {
         assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
         // If not a digit, a number greater than radix will be created.
         let mut digit = (self as u32).wrapping_sub('0' as u32);
@@ -345,7 +349,8 @@ impl char {
             // Force the 6th bit to be set to ensure ascii is lower case.
             digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10);
         }
-        (digit < radix).then_some(digit)
+        // FIXME: once then_some is const fn, use it here
+        if digit < radix { Some(digit) } else { None }
     }
 
     /// Returns an iterator that yields the hexadecimal Unicode escape of a
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7bc641c5276..43ba556af63 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -104,6 +104,7 @@
 #![feature(const_bigint_helper_methods)]
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
+#![feature(const_char_convert)]
 #![feature(const_discriminant)]
 #![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]