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