Fill in things needed to stabilize int_error_matching
This commit is contained in:
parent
fadf025723
commit
c027844795
9 changed files with 66 additions and 64 deletions
|
@ -46,7 +46,6 @@
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(int_error_matching)]
|
|
||||||
#![recursion_limit = "512"]
|
#![recursion_limit = "512"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -48,10 +48,12 @@ fn update_limit(
|
||||||
.unwrap_or(attr.span);
|
.unwrap_or(attr.span);
|
||||||
|
|
||||||
let error_str = match e.kind() {
|
let error_str = match e.kind() {
|
||||||
IntErrorKind::Overflow => "`limit` is too large",
|
IntErrorKind::PosOverflow => "`limit` is too large",
|
||||||
IntErrorKind::Empty => "`limit` must be a non-negative integer",
|
IntErrorKind::Empty | IntErrorKind::OnlySign => {
|
||||||
|
"`limit` must be a non-negative integer"
|
||||||
|
}
|
||||||
IntErrorKind::InvalidDigit => "not a valid 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`"),
|
IntErrorKind::Zero => bug!("zero is a valid `limit`"),
|
||||||
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
|
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,51 +77,47 @@ pub struct ParseIntError {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_error_matching)]
|
|
||||||
///
|
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// if let Err(e) = i32::from_str_radix("a12", 10) {
|
/// if let Err(e) = i32::from_str_radix("a12", 10) {
|
||||||
/// println!("Failed conversion to i32: {:?}", e.kind());
|
/// println!("Failed conversion to i32: {:?}", e.kind());
|
||||||
/// }
|
/// }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
feature = "int_error_matching",
|
|
||||||
reason = "it can be useful to match errors when making error messages \
|
|
||||||
for integer parsing",
|
|
||||||
issue = "22639"
|
|
||||||
)]
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum IntErrorKind {
|
pub enum IntErrorKind {
|
||||||
/// Value being parsed is empty.
|
/// Value being parsed is empty.
|
||||||
///
|
///
|
||||||
/// Among other causes, this variant will be constructed when parsing an empty string.
|
/// Among other causes, this variant will be constructed when parsing an empty string.
|
||||||
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
Empty,
|
Empty,
|
||||||
/// Contains an invalid digit.
|
/// Contains an invalid digit.
|
||||||
///
|
///
|
||||||
/// Among other causes, this variant will be constructed when parsing a string that
|
/// Among other causes, this variant will be constructed when parsing a string that
|
||||||
/// contains a letter.
|
/// contains a letter.
|
||||||
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
InvalidDigit,
|
InvalidDigit,
|
||||||
/// Integer is too large to store in target integer type.
|
/// 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.
|
/// Integer is too small to store in target integer type.
|
||||||
Underflow,
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
|
NegOverflow,
|
||||||
/// Value was Zero
|
/// Value was Zero
|
||||||
///
|
///
|
||||||
/// This variant will be emitted when the parsing string has a value of zero, which
|
/// This variant will be emitted when the parsing string has a value of zero, which
|
||||||
/// would be illegal for non-zero types.
|
/// would be illegal for non-zero types.
|
||||||
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
Zero,
|
Zero,
|
||||||
|
/// The value contains nothing other than signs `+` or `-`.
|
||||||
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
|
OnlySign,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseIntError {
|
impl ParseIntError {
|
||||||
/// Outputs the detailed cause of parsing an integer failing.
|
/// Outputs the detailed cause of parsing an integer failing.
|
||||||
#[unstable(
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
feature = "int_error_matching",
|
|
||||||
reason = "it can be useful to match errors when making error messages \
|
|
||||||
for integer parsing",
|
|
||||||
issue = "22639"
|
|
||||||
)]
|
|
||||||
pub fn kind(&self) -> &IntErrorKind {
|
pub fn kind(&self) -> &IntErrorKind {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
|
@ -136,9 +132,10 @@ impl ParseIntError {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IntErrorKind::Empty => "cannot parse integer from empty string",
|
IntErrorKind::Empty => "cannot parse integer from empty string",
|
||||||
IntErrorKind::InvalidDigit => "invalid digit found in string",
|
IntErrorKind::InvalidDigit => "invalid digit found in string",
|
||||||
IntErrorKind::Overflow => "number too large to fit in target type",
|
IntErrorKind::PosOverflow => "number too large to fit in target type",
|
||||||
IntErrorKind::Underflow => "number too small 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::Zero => "number would be zero for non-zero type",
|
||||||
|
IntErrorKind::OnlySign => "only signs without digits found in string",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No
|
||||||
#[stable(feature = "try_from", since = "1.34.0")]
|
#[stable(feature = "try_from", since = "1.34.0")]
|
||||||
pub use error::TryFromIntError;
|
pub use error::TryFromIntError;
|
||||||
|
|
||||||
#[unstable(feature = "int_error_matching", issue = "22639")]
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
pub use error::IntErrorKind;
|
pub use error::IntErrorKind;
|
||||||
|
|
||||||
macro_rules! usize_isize_to_xe_bytes_doc {
|
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() {
|
if digits.is_empty() {
|
||||||
return Err(PIE { kind: Empty });
|
return Err(PIE { kind: OnlySign });
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = T::from_u32(0);
|
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) {
|
result = match result.checked_mul(radix) {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return Err(PIE { kind: Overflow }),
|
None => return Err(PIE { kind: PosOverflow }),
|
||||||
};
|
};
|
||||||
result = match result.checked_add(x) {
|
result = match result.checked_add(x) {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return Err(PIE { kind: Overflow }),
|
None => return Err(PIE { kind: PosOverflow }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -865,11 +865,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
|
||||||
};
|
};
|
||||||
result = match result.checked_mul(radix) {
|
result = match result.checked_mul(radix) {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return Err(PIE { kind: Underflow }),
|
None => return Err(PIE { kind: NegOverflow }),
|
||||||
};
|
};
|
||||||
result = match result.checked_sub(x) {
|
result = match result.checked_sub(x) {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return Err(PIE { kind: Underflow }),
|
None => return Err(PIE { kind: NegOverflow }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#![feature(try_trait)]
|
#![feature(try_trait)]
|
||||||
#![feature(slice_internals)]
|
#![feature(slice_internals)]
|
||||||
#![feature(slice_partition_dedup)]
|
#![feature(slice_partition_dedup)]
|
||||||
#![feature(int_error_matching)]
|
|
||||||
#![feature(array_value_iter)]
|
#![feature(array_value_iter)]
|
||||||
#![feature(iter_partition_in_place)]
|
#![feature(iter_partition_in_place)]
|
||||||
#![feature(iter_is_partitioned)]
|
#![feature(iter_is_partitioned)]
|
||||||
|
|
|
@ -135,11 +135,11 @@ fn test_from_str() {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
|
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
|
||||||
Some(IntErrorKind::Underflow)
|
Some(IntErrorKind::NegOverflow)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
|
"257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
|
||||||
Some(IntErrorKind::Overflow)
|
Some(IntErrorKind::PosOverflow)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,11 @@ use core::cmp::PartialEq;
|
||||||
use core::convert::{TryFrom, TryInto};
|
use core::convert::{TryFrom, TryInto};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::marker::Copy;
|
use core::marker::Copy;
|
||||||
use core::num::TryFromIntError;
|
use core::num::{IntErrorKind, ParseIntError, TryFromIntError};
|
||||||
use core::ops::{Add, Div, Mul, Rem, Sub};
|
use core::ops::{Add, Div, Mul, Rem, Sub};
|
||||||
use core::option::Option;
|
use core::option::Option;
|
||||||
use core::option::Option::{None, Some};
|
use core::option::Option::None;
|
||||||
|
use core::str::FromStr;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod int_macros;
|
mod int_macros;
|
||||||
|
@ -65,6 +66,14 @@ where
|
||||||
assert_eq!(ten.rem(two), ten % two);
|
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]
|
#[test]
|
||||||
fn from_str_issue7588() {
|
fn from_str_issue7588() {
|
||||||
let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
|
let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
|
||||||
|
@ -75,49 +84,51 @@ fn from_str_issue7588() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_int_from_str_overflow() {
|
fn test_int_from_str_overflow() {
|
||||||
assert_eq!("127".parse::<i8>().ok(), Some(127i8));
|
test_parse::<i8>("127", Ok(127));
|
||||||
assert_eq!("128".parse::<i8>().ok(), None);
|
test_parse::<i8>("128", Err(IntErrorKind::PosOverflow));
|
||||||
|
|
||||||
assert_eq!("-128".parse::<i8>().ok(), Some(-128i8));
|
test_parse::<i8>("-128", Ok(-128));
|
||||||
assert_eq!("-129".parse::<i8>().ok(), None);
|
test_parse::<i8>("-129", Err(IntErrorKind::NegOverflow));
|
||||||
|
|
||||||
assert_eq!("32767".parse::<i16>().ok(), Some(32_767i16));
|
test_parse::<i16>("32767", Ok(32_767));
|
||||||
assert_eq!("32768".parse::<i16>().ok(), None);
|
test_parse::<i16>("32768", Err(IntErrorKind::PosOverflow));
|
||||||
|
|
||||||
assert_eq!("-32768".parse::<i16>().ok(), Some(-32_768i16));
|
test_parse::<i16>("-32768", Ok(-32_768));
|
||||||
assert_eq!("-32769".parse::<i16>().ok(), None);
|
test_parse::<i16>("-32769", Err(IntErrorKind::NegOverflow));
|
||||||
|
|
||||||
assert_eq!("2147483647".parse::<i32>().ok(), Some(2_147_483_647i32));
|
test_parse::<i32>("2147483647", Ok(2_147_483_647));
|
||||||
assert_eq!("2147483648".parse::<i32>().ok(), None);
|
test_parse::<i32>("2147483648", Err(IntErrorKind::PosOverflow));
|
||||||
|
|
||||||
assert_eq!("-2147483648".parse::<i32>().ok(), Some(-2_147_483_648i32));
|
test_parse::<i32>("-2147483648", Ok(-2_147_483_648));
|
||||||
assert_eq!("-2147483649".parse::<i32>().ok(), None);
|
test_parse::<i32>("-2147483649", Err(IntErrorKind::NegOverflow));
|
||||||
|
|
||||||
assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(9_223_372_036_854_775_807i64));
|
test_parse::<i64>("9223372036854775807", Ok(9_223_372_036_854_775_807));
|
||||||
assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
|
test_parse::<i64>("9223372036854775808", Err(IntErrorKind::PosOverflow));
|
||||||
|
|
||||||
assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(-9_223_372_036_854_775_808i64));
|
test_parse::<i64>("-9223372036854775808", Ok(-9_223_372_036_854_775_808));
|
||||||
assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
|
test_parse::<i64>("-9223372036854775809", Err(IntErrorKind::NegOverflow));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_leading_plus() {
|
fn test_leading_plus() {
|
||||||
assert_eq!("+127".parse::<u8>().ok(), Some(127));
|
test_parse::<u8>("+127", Ok(127));
|
||||||
assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807));
|
test_parse::<i64>("+9223372036854775807", Ok(9223372036854775807));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid() {
|
fn test_invalid() {
|
||||||
assert_eq!("--129".parse::<i8>().ok(), None);
|
test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit));
|
||||||
assert_eq!("++129".parse::<i8>().ok(), None);
|
test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit));
|
||||||
assert_eq!("Съешь".parse::<u8>().ok(), None);
|
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]
|
#[test]
|
||||||
fn test_empty() {
|
fn test_empty() {
|
||||||
assert_eq!("-".parse::<i8>().ok(), None);
|
test_parse::<i8>("-", Err(IntErrorKind::OnlySign));
|
||||||
assert_eq!("+".parse::<i8>().ok(), None);
|
test_parse::<i8>("+", Err(IntErrorKind::OnlySign));
|
||||||
assert_eq!("".parse::<u8>().ok(), None);
|
test_parse::<u8>("", Err(IntErrorKind::Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -264,7 +264,6 @@
|
||||||
#![feature(global_asm)]
|
#![feature(global_asm)]
|
||||||
#![feature(hashmap_internals)]
|
#![feature(hashmap_internals)]
|
||||||
#![feature(int_error_internals)]
|
#![feature(int_error_internals)]
|
||||||
#![feature(int_error_matching)]
|
|
||||||
#![feature(integer_atomics)]
|
#![feature(integer_atomics)]
|
||||||
#![feature(into_future)]
|
#![feature(into_future)]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
|
|
|
@ -22,12 +22,7 @@ pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8,
|
||||||
#[stable(feature = "nonzero", since = "1.28.0")]
|
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||||
pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
||||||
|
|
||||||
#[unstable(
|
#[stable(feature = "int_error_matching", since = "1.47.0")]
|
||||||
feature = "int_error_matching",
|
|
||||||
reason = "it can be useful to match errors when making error messages \
|
|
||||||
for integer parsing",
|
|
||||||
issue = "22639"
|
|
||||||
)]
|
|
||||||
pub use core::num::IntErrorKind;
|
pub use core::num::IntErrorKind;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue