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