Skip to main content

core/num/
error.rs

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