Skip to main content

core/num/
error.rs

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