core/num/
error.rs

1//! Error types for conversion to integral types.
2
3#[cfg(not(feature = "ferrocene_certified"))]
4use crate::convert::Infallible;
5#[cfg(not(feature = "ferrocene_certified"))]
6use crate::error::Error;
7#[cfg(not(feature = "ferrocene_certified"))]
8use crate::fmt;
9
10/// The error type returned when a checked integral type conversion fails.
11#[stable(feature = "try_from", since = "1.34.0")]
12#[cfg_attr(not(feature = "ferrocene_certified"), derive(Debug, Copy, Clone, PartialEq, Eq))]
13pub struct TryFromIntError(pub(crate) ());
14
15#[stable(feature = "try_from", since = "1.34.0")]
16#[cfg(not(feature = "ferrocene_certified"))]
17impl fmt::Display for TryFromIntError {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        "out of range integral type conversion attempted".fmt(f)
20    }
21}
22
23#[stable(feature = "try_from", since = "1.34.0")]
24#[cfg(not(feature = "ferrocene_certified"))]
25impl Error for TryFromIntError {}
26
27#[stable(feature = "try_from", since = "1.34.0")]
28#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
29#[cfg(not(feature = "ferrocene_certified"))]
30impl const From<Infallible> for TryFromIntError {
31    fn from(x: Infallible) -> TryFromIntError {
32        match x {}
33    }
34}
35
36#[unstable(feature = "never_type", issue = "35121")]
37#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
38#[cfg(not(feature = "ferrocene_certified"))]
39impl const From<!> for TryFromIntError {
40    #[inline]
41    fn from(never: !) -> TryFromIntError {
42        // Match rather than coerce to make sure that code like
43        // `From<Infallible> for TryFromIntError` above will keep working
44        // when `Infallible` becomes an alias to `!`.
45        match never {}
46    }
47}
48
49/// An error which can be returned when parsing an integer.
50///
51/// For example, this error is returned by the `from_str_radix()` functions
52/// on the primitive integer types (such as [`i8::from_str_radix`])
53/// and is used as the error type in their [`FromStr`] implementations.
54///
55/// [`FromStr`]: crate::str::FromStr
56///
57/// # Potential causes
58///
59/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
60/// in the string e.g., when it is obtained from the standard input.
61/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing.
62///
63/// # Example
64///
65/// ```
66/// if let Err(e) = i32::from_str_radix("a12", 10) {
67///     println!("Failed conversion to i32: {e}");
68/// }
69/// ```
70#[cfg_attr(not(feature = "ferrocene_certified"), derive(Debug, Clone, PartialEq, Eq))]
71#[stable(feature = "rust1", since = "1.0.0")]
72pub struct ParseIntError {
73    #[cfg_attr(feature = "ferrocene_certified", expect(dead_code))]
74    pub(super) kind: IntErrorKind,
75}
76
77/// Enum to store the various types of errors that can cause parsing an integer to fail.
78///
79/// # Example
80///
81/// ```
82/// # fn main() {
83/// if let Err(e) = i32::from_str_radix("a12", 10) {
84///     println!("Failed conversion to i32: {:?}", e.kind());
85/// }
86/// # }
87/// ```
88#[stable(feature = "int_error_matching", since = "1.55.0")]
89#[cfg_attr(not(feature = "ferrocene_certified"), derive(Debug, Clone, PartialEq, Eq, Copy, Hash))]
90#[non_exhaustive]
91pub enum IntErrorKind {
92    /// Value being parsed is empty.
93    ///
94    /// This variant will be constructed when parsing an empty string.
95    #[stable(feature = "int_error_matching", since = "1.55.0")]
96    Empty,
97    /// Contains an invalid digit in its context.
98    ///
99    /// Among other causes, this variant will be constructed when parsing a string that
100    /// contains a non-ASCII char.
101    ///
102    /// This variant is also constructed when a `+` or `-` is misplaced within a string
103    /// either on its own or in the middle of a number.
104    #[stable(feature = "int_error_matching", since = "1.55.0")]
105    InvalidDigit,
106    /// Integer is too large to store in target integer type.
107    #[stable(feature = "int_error_matching", since = "1.55.0")]
108    PosOverflow,
109    /// Integer is too small to store in target integer type.
110    #[stable(feature = "int_error_matching", since = "1.55.0")]
111    NegOverflow,
112    /// Value was Zero
113    ///
114    /// This variant will be emitted when the parsing string has a value of zero, which
115    /// would be illegal for non-zero types.
116    #[stable(feature = "int_error_matching", since = "1.55.0")]
117    Zero,
118}
119
120#[cfg(not(feature = "ferrocene_certified"))]
121impl ParseIntError {
122    /// Outputs the detailed cause of parsing an integer failing.
123    #[must_use]
124    #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
125    #[stable(feature = "int_error_matching", since = "1.55.0")]
126    pub const fn kind(&self) -> &IntErrorKind {
127        &self.kind
128    }
129}
130
131#[stable(feature = "rust1", since = "1.0.0")]
132#[cfg(not(feature = "ferrocene_certified"))]
133impl fmt::Display for ParseIntError {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        match self.kind {
136            IntErrorKind::Empty => "cannot parse integer from empty string",
137            IntErrorKind::InvalidDigit => "invalid digit found in string",
138            IntErrorKind::PosOverflow => "number too large to fit in target type",
139            IntErrorKind::NegOverflow => "number too small to fit in target type",
140            IntErrorKind::Zero => "number would be zero for non-zero type",
141        }
142        .fmt(f)
143    }
144}
145
146#[stable(feature = "rust1", since = "1.0.0")]
147#[cfg(not(feature = "ferrocene_certified"))]
148impl Error for ParseIntError {}