core2/error.rs
1//! Traits for working with Errors.
2
3// A note about crates and the facade:
4//
5// Originally, the `Error` trait was defined in libcore, and the impls
6// were scattered about. However, coherence objected to this
7// arrangement, because to create the blanket impls for `Box` required
8// knowing that `&str: !Error`, and we have no means to deal with that
9// sort of conflict just now. Therefore, for the time being, we have
10// moved the `Error` trait into libstd. As we evolve a sol'n to the
11// coherence challenge (e.g., specialization, neg impls, etc) we can
12// reconsider what crate these items belong in.
13
14#[allow(deprecated)]
15use core::alloc::LayoutErr;
16
17use core::any::TypeId;
18use core::fmt::{Debug, Display};
19
20#[cfg(feature = "alloc")]
21use alloc::{string::String, borrow::Cow, boxed::Box};
22
23/// `Error` is a trait representing the basic expectations for error values,
24/// i.e., values of type `E` in [`Result<T, E>`]. Errors must describe
25/// themselves through the [`Display`] and [`Debug`] traits, and may provide
26/// cause chain information:
27///
28/// [`Error::source()`] is generally used when errors cross
29/// "abstraction boundaries". If one module must report an error that is caused
30/// by an error from a lower-level module, it can allow accessing that error
31/// via [`Error::source()`]. This makes it possible for the high-level
32/// module to provide its own errors while also revealing some of the
33/// implementation for debugging via `source` chains.
34///
35/// [`Result<T, E>`]: Result
36pub trait Error: Debug + Display {
37 /// The lower-level source of this error, if any.
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use std::error::Error;
43 /// use std::fmt;
44 ///
45 /// #[derive(Debug)]
46 /// struct SuperError {
47 /// side: SuperErrorSideKick,
48 /// }
49 ///
50 /// impl fmt::Display for SuperError {
51 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 /// write!(f, "SuperError is here!")
53 /// }
54 /// }
55 ///
56 /// impl Error for SuperError {
57 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
58 /// Some(&self.side)
59 /// }
60 /// }
61 ///
62 /// #[derive(Debug)]
63 /// struct SuperErrorSideKick;
64 ///
65 /// impl fmt::Display for SuperErrorSideKick {
66 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 /// write!(f, "SuperErrorSideKick is here!")
68 /// }
69 /// }
70 ///
71 /// impl Error for SuperErrorSideKick {}
72 ///
73 /// fn get_super_error() -> Result<(), SuperError> {
74 /// Err(SuperError { side: SuperErrorSideKick })
75 /// }
76 ///
77 /// fn main() {
78 /// match get_super_error() {
79 /// Err(e) => {
80 /// println!("Error: {}", e);
81 /// println!("Caused by: {}", e.source().unwrap());
82 /// }
83 /// _ => println!("No error"),
84 /// }
85 /// }
86 /// ```
87 fn source(&self) -> Option<&(dyn Error + 'static)> {
88 None
89 }
90
91 /// Gets the `TypeId` of `self`.
92 #[doc(hidden)]
93 fn type_id(&self, _: private::Internal) -> TypeId
94 where
95 Self: 'static,
96 {
97 TypeId::of::<Self>()
98 }
99}
100
101mod private {
102 // This is a hack to prevent `type_id` from being overridden by `Error`
103 // implementations, since that can enable unsound downcasting.
104 #[derive(Debug)]
105 pub struct Internal;
106}
107
108#[cfg(feature = "alloc")]
109impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
110 /// Converts a type of [`Error`] into a box of dyn [`Error`].
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use std::error::Error;
116 /// use std::fmt;
117 /// use std::mem;
118 ///
119 /// #[derive(Debug)]
120 /// struct AnError;
121 ///
122 /// impl fmt::Display for AnError {
123 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 /// write!(f , "An error")
125 /// }
126 /// }
127 ///
128 /// impl Error for AnError {}
129 ///
130 /// let an_error = AnError;
131 /// assert!(0 == mem::size_of_val(&an_error));
132 /// let a_boxed_error = Box::<dyn Error>::from(an_error);
133 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
134 /// ```
135 fn from(err: E) -> Box<dyn Error + 'a> {
136 Box::new(err)
137 }
138}
139
140#[cfg(feature = "alloc")]
141impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
142 /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
143 /// dyn [`Error`] + [`Send`] + [`Sync`].
144 ///
145 /// # Examples
146 ///
147 /// ```
148 /// use std::error::Error;
149 /// use std::fmt;
150 /// use std::mem;
151 ///
152 /// #[derive(Debug)]
153 /// struct AnError;
154 ///
155 /// impl fmt::Display for AnError {
156 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 /// write!(f , "An error")
158 /// }
159 /// }
160 ///
161 /// impl Error for AnError {}
162 ///
163 /// unsafe impl Send for AnError {}
164 ///
165 /// unsafe impl Sync for AnError {}
166 ///
167 /// let an_error = AnError;
168 /// assert!(0 == mem::size_of_val(&an_error));
169 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
170 /// assert!(
171 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
172 /// ```
173 fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
174 Box::new(err)
175 }
176}
177
178#[cfg(feature = "alloc")]
179impl From<String> for Box<dyn Error + Send + Sync> {
180 /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
181 ///
182 /// # Examples
183 ///
184 /// ```
185 /// use std::error::Error;
186 /// use std::mem;
187 ///
188 /// let a_string_error = "a string error".to_string();
189 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
190 /// assert!(
191 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
192 /// ```
193 #[inline]
194 fn from(err: String) -> Box<dyn Error + Send + Sync> {
195 struct StringError(String);
196
197 impl Error for StringError {}
198
199 impl Display for StringError {
200 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
201 Display::fmt(&self.0, f)
202 }
203 }
204
205 // Purposefully skip printing "StringError(..)"
206 impl Debug for StringError {
207 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208 Debug::fmt(&self.0, f)
209 }
210 }
211
212 Box::new(StringError(err))
213 }
214}
215
216#[cfg(feature = "alloc")]
217impl From<String> for Box<dyn Error> {
218 /// Converts a [`String`] into a box of dyn [`Error`].
219 ///
220 /// # Examples
221 ///
222 /// ```
223 /// use std::error::Error;
224 /// use std::mem;
225 ///
226 /// let a_string_error = "a string error".to_string();
227 /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
228 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
229 /// ```
230 fn from(str_err: String) -> Box<dyn Error> {
231 let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
232 let err2: Box<dyn Error> = err1;
233 err2
234 }
235}
236
237#[cfg(feature = "alloc")]
238impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
239 /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
240 ///
241 /// [`str`]: prim@str
242 ///
243 /// # Examples
244 ///
245 /// ```
246 /// use std::error::Error;
247 /// use std::mem;
248 ///
249 /// let a_str_error = "a str error";
250 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
251 /// assert!(
252 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
253 /// ```
254 #[inline]
255 fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
256 From::from(String::from(err))
257 }
258}
259
260#[cfg(feature = "alloc")]
261impl From<&str> for Box<dyn Error> {
262 /// Converts a [`str`] into a box of dyn [`Error`].
263 ///
264 /// [`str`]: prim@str
265 ///
266 /// # Examples
267 ///
268 /// ```
269 /// use std::error::Error;
270 /// use std::mem;
271 ///
272 /// let a_str_error = "a str error";
273 /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
274 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
275 /// ```
276 fn from(err: &str) -> Box<dyn Error> {
277 From::from(String::from(err))
278 }
279}
280
281#[cfg(feature = "alloc")]
282impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
283 /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
284 ///
285 /// # Examples
286 ///
287 /// ```
288 /// use std::error::Error;
289 /// use std::mem;
290 /// use std::borrow::Cow;
291 ///
292 /// let a_cow_str_error = Cow::from("a str error");
293 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
294 /// assert!(
295 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
296 /// ```
297 fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
298 From::from(String::from(err))
299 }
300}
301
302#[cfg(feature = "alloc")]
303impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
304 /// Converts a [`Cow`] into a box of dyn [`Error`].
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// use std::error::Error;
310 /// use std::mem;
311 /// use std::borrow::Cow;
312 ///
313 /// let a_cow_str_error = Cow::from("a str error");
314 /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
315 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
316 /// ```
317 fn from(err: Cow<'a, str>) -> Box<dyn Error> {
318 From::from(String::from(err))
319 }
320}
321
322// #[unstable(feature = "never_type", issue = "35121")]
323#[cfg(feature = "nightly")]
324impl Error for ! {}
325
326#[allow(deprecated)]
327impl Error for LayoutErr {}
328
329impl Error for core::str::ParseBoolError {}
330
331impl Error for core::str::Utf8Error {}
332
333impl Error for core::num::ParseIntError {}
334
335impl Error for core::num::TryFromIntError {}
336
337impl Error for core::array::TryFromSliceError {}
338
339impl Error for core::num::ParseFloatError {}
340
341#[cfg(feature = "alloc")]
342impl Error for alloc::string::FromUtf8Error {}
343
344#[cfg(feature = "alloc")]
345impl Error for alloc::string::FromUtf16Error {}
346
347
348#[cfg(feature = "alloc")]
349impl<T: Error> Error for Box<T> {
350 fn source(&self) -> Option<&(dyn Error + 'static)> {
351 Error::source(&**self)
352 }
353}
354
355// Copied from `any.rs`.
356impl dyn Error + 'static {
357 /// Returns `true` if the boxed type is the same as `T`
358 #[inline]
359 pub fn is<T: Error + 'static>(&self) -> bool {
360 // Get `TypeId` of the type this function is instantiated with.
361 let t = TypeId::of::<T>();
362
363 // Get `TypeId` of the type in the trait object.
364 let boxed = self.type_id(private::Internal);
365
366 // Compare both `TypeId`s on equality.
367 t == boxed
368 }
369
370 /// Returns some reference to the boxed value if it is of type `T`, or
371 /// `None` if it isn't.
372 #[inline]
373 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
374 if self.is::<T>() {
375 unsafe { Some(&*(self as *const dyn Error as *const T)) }
376 } else {
377 None
378 }
379 }
380
381 /// Returns some mutable reference to the boxed value if it is of type `T`, or
382 /// `None` if it isn't.
383 #[inline]
384 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
385 if self.is::<T>() {
386 unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
387 } else {
388 None
389 }
390 }
391}
392
393impl dyn Error + 'static + Send {
394 /// Forwards to the method defined on the type `dyn Error`.
395 #[inline]
396 pub fn is<T: Error + 'static>(&self) -> bool {
397 <dyn Error + 'static>::is::<T>(self)
398 }
399
400 /// Forwards to the method defined on the type `dyn Error`.
401 #[inline]
402 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
403 <dyn Error + 'static>::downcast_ref::<T>(self)
404 }
405
406 /// Forwards to the method defined on the type `dyn Error`.
407 #[inline]
408 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
409 <dyn Error + 'static>::downcast_mut::<T>(self)
410 }
411}
412
413impl dyn Error + 'static + Send + Sync {
414 /// Forwards to the method defined on the type `dyn Error`.
415 #[inline]
416 pub fn is<T: Error + 'static>(&self) -> bool {
417 <dyn Error + 'static>::is::<T>(self)
418 }
419
420 /// Forwards to the method defined on the type `dyn Error`.
421 #[inline]
422 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
423 <dyn Error + 'static>::downcast_ref::<T>(self)
424 }
425
426 /// Forwards to the method defined on the type `dyn Error`.
427 #[inline]
428 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
429 <dyn Error + 'static>::downcast_mut::<T>(self)
430 }
431}
432
433#[cfg(feature = "alloc")]
434impl dyn Error {
435 #[inline]
436 /// Attempts to downcast the box to a concrete type.
437 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
438 if self.is::<T>() {
439 unsafe {
440 let raw: *mut dyn Error = Box::into_raw(self);
441 Ok(Box::from_raw(raw as *mut T))
442 }
443 } else {
444 Err(self)
445 }
446 }
447}
448
449#[cfg(feature = "alloc")]
450impl dyn Error + Send {
451 #[inline]
452 /// Attempts to downcast the box to a concrete type.
453 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
454 let err: Box<dyn Error> = self;
455 <dyn Error>::downcast(err).map_err(|s| unsafe {
456 // Reapply the `Send` marker.
457 core::mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
458 })
459 }
460}
461
462#[cfg(feature = "alloc")]
463impl dyn Error + Send + Sync {
464 #[inline]
465 /// Attempts to downcast the box to a concrete type.
466 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
467 let err: Box<dyn Error> = self;
468 <dyn Error>::downcast(err).map_err(|s| unsafe {
469 // Reapply the `Send + Sync` marker.
470 core::mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
471 })
472 }
473}