about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEthan Brierley <ethanboxx@gmail.com>2020-10-06 14:06:25 +0100
committerEthan Brierley <ethanboxx@gmail.com>2020-10-06 14:06:25 +0100
commitc027844795e427e63ef917ba40c71d0559d88b79 (patch)
treea6981f116dc3a4b8cc48e376b686b974a47dcaa6
parentfadf0257235ddb8a464befc02e50b35652174689 (diff)
downloadrust-c027844795e427e63ef917ba40c71d0559d88b79.tar.gz
rust-c027844795e427e63ef917ba40c71d0559d88b79.zip
Fill in things needed to stabilize int_error_matching
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs8
-rw-r--r--library/core/src/num/error.rs33
-rw-r--r--library/core/src/num/mod.rs12
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/nonzero.rs4
-rw-r--r--library/core/tests/num/mod.rs63
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/num.rs7
9 files changed, 66 insertions, 64 deletions
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index fa885ce2e7c..37bc1a305b2 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -46,7 +46,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
-#![feature(int_error_matching)]
 #![recursion_limit = "512"]
 
 #[macro_use]
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index def9e5ebb52..6b6df3a303c 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -48,10 +48,12 @@ fn update_limit(
                         .unwrap_or(attr.span);
 
                     let error_str = match e.kind() {
-                        IntErrorKind::Overflow => "`limit` is too large",
-                        IntErrorKind::Empty => "`limit` must be a non-negative integer",
+                        IntErrorKind::PosOverflow => "`limit` is too large",
+                        IntErrorKind::Empty | IntErrorKind::OnlySign => {
+                            "`limit` must be a non-negative integer"
+                        }
                         IntErrorKind::InvalidDigit => "not a valid integer",
-                        IntErrorKind::Underflow => bug!("`limit` should never underflow"),
+                        IntErrorKind::NegOverflow => bug!("`limit` should never underflow"),
                         IntErrorKind::Zero => bug!("zero is a valid `limit`"),
                         kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
                     };
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index aab17155186..9705226ba24 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -77,51 +77,47 @@ pub struct ParseIntError {
 /// # Example
 ///
 /// ```
-/// #![feature(int_error_matching)]
-///
 /// # fn main() {
 /// if let Err(e) = i32::from_str_radix("a12", 10) {
 ///     println!("Failed conversion to i32: {:?}", e.kind());
 /// }
 /// # }
 /// ```
-#[unstable(
-    feature = "int_error_matching",
-    reason = "it can be useful to match errors when making error messages \
-              for integer parsing",
-    issue = "22639"
-)]
+#[stable(feature = "int_error_matching", since = "1.47.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[non_exhaustive]
 pub enum IntErrorKind {
     /// Value being parsed is empty.
     ///
     /// Among other causes, this variant will be constructed when parsing an empty string.
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
     Empty,
     /// Contains an invalid digit.
     ///
     /// Among other causes, this variant will be constructed when parsing a string that
     /// contains a letter.
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
     InvalidDigit,
     /// Integer is too large to store in target integer type.
-    Overflow,
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
+    PosOverflow,
     /// Integer is too small to store in target integer type.
-    Underflow,
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
+    NegOverflow,
     /// Value was Zero
     ///
     /// This variant will be emitted when the parsing string has a value of zero, which
     /// would be illegal for non-zero types.
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
     Zero,
+    /// The value contains nothing other than signs `+` or `-`.
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
+    OnlySign,
 }
 
 impl ParseIntError {
     /// Outputs the detailed cause of parsing an integer failing.
-    #[unstable(
-        feature = "int_error_matching",
-        reason = "it can be useful to match errors when making error messages \
-                  for integer parsing",
-        issue = "22639"
-    )]
+    #[stable(feature = "int_error_matching", since = "1.47.0")]
     pub fn kind(&self) -> &IntErrorKind {
         &self.kind
     }
@@ -136,9 +132,10 @@ impl ParseIntError {
         match self.kind {
             IntErrorKind::Empty => "cannot parse integer from empty string",
             IntErrorKind::InvalidDigit => "invalid digit found in string",
-            IntErrorKind::Overflow => "number too large to fit in target type",
-            IntErrorKind::Underflow => "number too small to fit in target type",
+            IntErrorKind::PosOverflow => "number too large to fit in target type",
+            IntErrorKind::NegOverflow => "number too small to fit in target type",
             IntErrorKind::Zero => "number would be zero for non-zero type",
+            IntErrorKind::OnlySign => "only signs without digits found in string",
         }
     }
 }
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 4f64e30ccf8..67b4b885dd2 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -63,7 +63,7 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No
 #[stable(feature = "try_from", since = "1.34.0")]
 pub use error::TryFromIntError;
 
-#[unstable(feature = "int_error_matching", issue = "22639")]
+#[stable(feature = "int_error_matching", since = "1.47.0")]
 pub use error::IntErrorKind;
 
 macro_rules! usize_isize_to_xe_bytes_doc {
@@ -836,7 +836,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
     };
 
     if digits.is_empty() {
-        return Err(PIE { kind: Empty });
+        return Err(PIE { kind: OnlySign });
     }
 
     let mut result = T::from_u32(0);
@@ -849,11 +849,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
             };
             result = match result.checked_mul(radix) {
                 Some(result) => result,
-                None => return Err(PIE { kind: Overflow }),
+                None => return Err(PIE { kind: PosOverflow }),
             };
             result = match result.checked_add(x) {
                 Some(result) => result,
-                None => return Err(PIE { kind: Overflow }),
+                None => return Err(PIE { kind: PosOverflow }),
             };
         }
     } else {
@@ -865,11 +865,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
             };
             result = match result.checked_mul(radix) {
                 Some(result) => result,
-                None => return Err(PIE { kind: Underflow }),
+                None => return Err(PIE { kind: NegOverflow }),
             };
             result = match result.checked_sub(x) {
                 Some(result) => result,
-                None => return Err(PIE { kind: Underflow }),
+                None => return Err(PIE { kind: NegOverflow }),
             };
         }
     }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index d8b36beb3e0..c128691fa75 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -37,7 +37,6 @@
 #![feature(try_trait)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
-#![feature(int_error_matching)]
 #![feature(array_value_iter)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs
index 825e5e63b59..fb1293c99bb 100644
--- a/library/core/tests/nonzero.rs
+++ b/library/core/tests/nonzero.rs
@@ -135,11 +135,11 @@ fn test_from_str() {
     );
     assert_eq!(
         "-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
-        Some(IntErrorKind::Underflow)
+        Some(IntErrorKind::NegOverflow)
     );
     assert_eq!(
         "257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
-        Some(IntErrorKind::Overflow)
+        Some(IntErrorKind::PosOverflow)
     );
 }
 
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 939f1325c84..d6f92f25e78 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -2,10 +2,11 @@ use core::cmp::PartialEq;
 use core::convert::{TryFrom, TryInto};
 use core::fmt::Debug;
 use core::marker::Copy;
-use core::num::TryFromIntError;
+use core::num::{IntErrorKind, ParseIntError, TryFromIntError};
 use core::ops::{Add, Div, Mul, Rem, Sub};
 use core::option::Option;
-use core::option::Option::{None, Some};
+use core::option::Option::None;
+use core::str::FromStr;
 
 #[macro_use]
 mod int_macros;
@@ -65,6 +66,14 @@ where
     assert_eq!(ten.rem(two), ten % two);
 }
 
+fn test_parse<T>(num_str: &str, expected: Result<T, IntErrorKind>)
+where
+    T: FromStr<Err = ParseIntError>,
+    Result<T, IntErrorKind>: PartialEq + Debug,
+{
+    assert_eq!(num_str.parse::<T>().map_err(|e| e.kind().clone()), expected)
+}
+
 #[test]
 fn from_str_issue7588() {
     let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
@@ -75,49 +84,51 @@ fn from_str_issue7588() {
 
 #[test]
 fn test_int_from_str_overflow() {
-    assert_eq!("127".parse::<i8>().ok(), Some(127i8));
-    assert_eq!("128".parse::<i8>().ok(), None);
+    test_parse::<i8>("127", Ok(127));
+    test_parse::<i8>("128", Err(IntErrorKind::PosOverflow));
 
-    assert_eq!("-128".parse::<i8>().ok(), Some(-128i8));
-    assert_eq!("-129".parse::<i8>().ok(), None);
+    test_parse::<i8>("-128", Ok(-128));
+    test_parse::<i8>("-129", Err(IntErrorKind::NegOverflow));
 
-    assert_eq!("32767".parse::<i16>().ok(), Some(32_767i16));
-    assert_eq!("32768".parse::<i16>().ok(), None);
+    test_parse::<i16>("32767", Ok(32_767));
+    test_parse::<i16>("32768", Err(IntErrorKind::PosOverflow));
 
-    assert_eq!("-32768".parse::<i16>().ok(), Some(-32_768i16));
-    assert_eq!("-32769".parse::<i16>().ok(), None);
+    test_parse::<i16>("-32768", Ok(-32_768));
+    test_parse::<i16>("-32769", Err(IntErrorKind::NegOverflow));
 
-    assert_eq!("2147483647".parse::<i32>().ok(), Some(2_147_483_647i32));
-    assert_eq!("2147483648".parse::<i32>().ok(), None);
+    test_parse::<i32>("2147483647", Ok(2_147_483_647));
+    test_parse::<i32>("2147483648", Err(IntErrorKind::PosOverflow));
 
-    assert_eq!("-2147483648".parse::<i32>().ok(), Some(-2_147_483_648i32));
-    assert_eq!("-2147483649".parse::<i32>().ok(), None);
+    test_parse::<i32>("-2147483648", Ok(-2_147_483_648));
+    test_parse::<i32>("-2147483649", Err(IntErrorKind::NegOverflow));
 
-    assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(9_223_372_036_854_775_807i64));
-    assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
+    test_parse::<i64>("9223372036854775807", Ok(9_223_372_036_854_775_807));
+    test_parse::<i64>("9223372036854775808", Err(IntErrorKind::PosOverflow));
 
-    assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(-9_223_372_036_854_775_808i64));
-    assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
+    test_parse::<i64>("-9223372036854775808", Ok(-9_223_372_036_854_775_808));
+    test_parse::<i64>("-9223372036854775809", Err(IntErrorKind::NegOverflow));
 }
 
 #[test]
 fn test_leading_plus() {
-    assert_eq!("+127".parse::<u8>().ok(), Some(127));
-    assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807));
+    test_parse::<u8>("+127", Ok(127));
+    test_parse::<i64>("+9223372036854775807", Ok(9223372036854775807));
 }
 
 #[test]
 fn test_invalid() {
-    assert_eq!("--129".parse::<i8>().ok(), None);
-    assert_eq!("++129".parse::<i8>().ok(), None);
-    assert_eq!("Съешь".parse::<u8>().ok(), None);
+    test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit));
+    test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit));
+    test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit));
+    // is this the correct error here. Maybe need a reapeat sign error here
+    test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit));
 }
 
 #[test]
 fn test_empty() {
-    assert_eq!("-".parse::<i8>().ok(), None);
-    assert_eq!("+".parse::<i8>().ok(), None);
-    assert_eq!("".parse::<u8>().ok(), None);
+    test_parse::<i8>("-", Err(IntErrorKind::OnlySign));
+    test_parse::<i8>("+", Err(IntErrorKind::OnlySign));
+    test_parse::<u8>("", Err(IntErrorKind::Empty));
 }
 
 #[test]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ac0075ad129..fa23229066c 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -264,7 +264,6 @@
 #![feature(global_asm)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
-#![feature(int_error_matching)]
 #![feature(integer_atomics)]
 #![feature(into_future)]
 #![feature(lang_items)]
diff --git a/library/std/src/num.rs b/library/std/src/num.rs
index 0f1c5962685..ac3b055cdb0 100644
--- a/library/std/src/num.rs
+++ b/library/std/src/num.rs
@@ -22,12 +22,7 @@ pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8,
 #[stable(feature = "nonzero", since = "1.28.0")]
 pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
-#[unstable(
-    feature = "int_error_matching",
-    reason = "it can be useful to match errors when making error messages \
-              for integer parsing",
-    issue = "22639"
-)]
+#[stable(feature = "int_error_matching", since = "1.47.0")]
 pub use core::num::IntErrorKind;
 
 #[cfg(test)]