core/num/
error.rs

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