]> git.lizzy.rs Git - rust.git/blob - library/core/src/num/error.rs
Auto merge of #95454 - randomicon00:fix95444, r=wesleywiser
[rust.git] / library / core / src / num / error.rs
1 //! Error types for conversion to integral types.
2
3 use crate::convert::Infallible;
4 use 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)]
9 pub struct TryFromIntError(pub(crate) ());
10
11 impl TryFromIntError {
12     #[unstable(
13         feature = "int_error_internals",
14         reason = "available through Error trait and this method should \
15                   not be exposed publicly",
16         issue = "none"
17     )]
18     #[doc(hidden)]
19     pub fn __description(&self) -> &str {
20         "out of range integral type conversion attempted"
21     }
22 }
23
24 #[stable(feature = "try_from", since = "1.34.0")]
25 impl fmt::Display for TryFromIntError {
26     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
27         self.__description().fmt(fmt)
28     }
29 }
30
31 #[stable(feature = "try_from", since = "1.34.0")]
32 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
33 impl 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 impl const From<!> for TryFromIntError {
41     fn from(never: !) -> TryFromIntError {
42         // Match rather than coerce to make sure that code like
43         // `From<Infallible> for TryFromIntError` above will keep working
44         // when `Infallible` becomes an alias to `!`.
45         match never {}
46     }
47 }
48
49 /// An error which can be returned when parsing an integer.
50 ///
51 /// This error is used as the error type for the `from_str_radix()` functions
52 /// on the primitive integer types, such as [`i8::from_str_radix`].
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")]
69 pub struct ParseIntError {
70     pub(super) kind: IntErrorKind,
71 }
72
73 /// Enum to store the various types of errors that can cause parsing an integer to fail.
74 ///
75 /// # Example
76 ///
77 /// ```
78 /// # fn main() {
79 /// if let Err(e) = i32::from_str_radix("a12", 10) {
80 ///     println!("Failed conversion to i32: {:?}", e.kind());
81 /// }
82 /// # }
83 /// ```
84 #[stable(feature = "int_error_matching", since = "1.55.0")]
85 #[derive(Debug, Clone, PartialEq, Eq)]
86 #[non_exhaustive]
87 pub enum IntErrorKind {
88     /// Value being parsed is empty.
89     ///
90     /// This variant will be constructed when parsing an empty string.
91     #[stable(feature = "int_error_matching", since = "1.55.0")]
92     Empty,
93     /// Contains an invalid digit in its context.
94     ///
95     /// Among other causes, this variant will be constructed when parsing a string that
96     /// contains a non-ASCII char.
97     ///
98     /// This variant is also constructed when a `+` or `-` is misplaced within a string
99     /// either on its own or in the middle of a number.
100     #[stable(feature = "int_error_matching", since = "1.55.0")]
101     InvalidDigit,
102     /// Integer is too large to store in target integer type.
103     #[stable(feature = "int_error_matching", since = "1.55.0")]
104     PosOverflow,
105     /// Integer is too small to store in target integer type.
106     #[stable(feature = "int_error_matching", since = "1.55.0")]
107     NegOverflow,
108     /// Value was Zero
109     ///
110     /// This variant will be emitted when the parsing string has a value of zero, which
111     /// would be illegal for non-zero types.
112     #[stable(feature = "int_error_matching", since = "1.55.0")]
113     Zero,
114 }
115
116 impl ParseIntError {
117     /// Outputs the detailed cause of parsing an integer failing.
118     #[must_use]
119     #[stable(feature = "int_error_matching", since = "1.55.0")]
120     pub fn kind(&self) -> &IntErrorKind {
121         &self.kind
122     }
123     #[unstable(
124         feature = "int_error_internals",
125         reason = "available through Error trait and this method should \
126                   not be exposed publicly",
127         issue = "none"
128     )]
129     #[doc(hidden)]
130     pub fn __description(&self) -> &str {
131         match self.kind {
132             IntErrorKind::Empty => "cannot parse integer from empty string",
133             IntErrorKind::InvalidDigit => "invalid digit found in string",
134             IntErrorKind::PosOverflow => "number too large to fit in target type",
135             IntErrorKind::NegOverflow => "number too small to fit in target type",
136             IntErrorKind::Zero => "number would be zero for non-zero type",
137         }
138     }
139 }
140
141 #[stable(feature = "rust1", since = "1.0.0")]
142 impl fmt::Display for ParseIntError {
143     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144         self.__description().fmt(f)
145     }
146 }