1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Traits for working with Errors.
13 //! # The `Error` trait
15 //! `Error` is a trait representing the basic expectations for error values,
16 //! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
17 //! a description, but they may optionally provide additional detail (via
18 //! `Display`) and cause chain information:
21 //! use std::fmt::Display;
23 //! trait Error: Display {
24 //! fn description(&self) -> &str;
26 //! fn cause(&self) -> Option<&Error> { None }
30 //! The `cause` method is generally used when errors cross "abstraction
31 //! boundaries", i.e. when a one module must report an error that is "caused"
32 //! by an error from a lower-level module. This setup makes it possible for the
33 //! high-level module to provide its own errors that do not commit to any
34 //! particular implementation, but also reveal some of its implementation for
35 //! debugging via `cause` chains.
37 #![stable(feature = "rust1", since = "1.0.0")]
39 // A note about crates and the facade:
41 // Originally, the `Error` trait was defined in libcore, and the impls
42 // were scattered about. However, coherence objected to this
43 // arrangement, because to create the blanket impls for `Box` required
44 // knowing that `&str: !Error`, and we have no means to deal with that
45 // sort of conflict just now. Therefore, for the time being, we have
46 // moved the `Error` trait into libstd. As we evolve a sol'n to the
47 // coherence challenge (e.g., specialization, neg impls, etc) we can
48 // reconsider what crate these items belong in.
54 use fmt
::{self, Debug, Display}
;
55 use marker
::{Send, Sync, Reflect}
;
60 use string
::{self, String}
;
62 /// Base functionality for all errors in Rust.
63 #[stable(feature = "rust1", since = "1.0.0")]
64 pub trait Error
: Debug
+ Display
+ Reflect
{
65 /// A short description of the error.
67 /// The description should not contain newlines or sentence-ending
68 /// punctuation, to facilitate embedding in larger user-facing
74 /// use std::error::Error;
76 /// match "xc".parse::<u32>() {
78 /// println!("Error: {}", e.description());
80 /// _ => println!("No error"),
83 #[stable(feature = "rust1", since = "1.0.0")]
84 fn description(&self) -> &str;
86 /// The lower-level cause of this error, if any.
91 /// use std::error::Error;
95 /// struct SuperError {
96 /// side: SuperErrorSideKick,
99 /// impl fmt::Display for SuperError {
100 /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 /// write!(f, "SuperError is here!")
105 /// impl Error for SuperError {
106 /// fn description(&self) -> &str {
107 /// "I'm the superhero of errors!"
110 /// fn cause(&self) -> Option<&Error> {
116 /// struct SuperErrorSideKick;
118 /// impl fmt::Display for SuperErrorSideKick {
119 /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 /// write!(f, "SuperErrorSideKick is here!")
124 /// impl Error for SuperErrorSideKick {
125 /// fn description(&self) -> &str {
126 /// "I'm SuperError side kick!"
130 /// fn get_super_error() -> Result<(), SuperError> {
131 /// Err(SuperError { side: SuperErrorSideKick })
135 /// match get_super_error() {
137 /// println!("Error: {}", e.description());
138 /// println!("Caused by: {}", e.cause().unwrap());
140 /// _ => println!("No error"),
144 #[stable(feature = "rust1", since = "1.0.0")]
145 fn cause(&self) -> Option
<&Error
> { None }
147 /// Get the `TypeId` of `self`
149 #[unstable(feature = "error_type_id",
150 reason
= "unclear whether to commit to this public implementation detail",
152 fn type_id(&self) -> TypeId
where Self: '
static {
157 #[stable(feature = "rust1", since = "1.0.0")]
158 impl<'a
, E
: Error
+ 'a
> From
<E
> for Box
<Error
+ 'a
> {
159 fn from(err
: E
) -> Box
<Error
+ 'a
> {
164 #[stable(feature = "rust1", since = "1.0.0")]
165 impl<'a
, E
: Error
+ Send
+ Sync
+ 'a
> From
<E
> for Box
<Error
+ Send
+ Sync
+ 'a
> {
166 fn from(err
: E
) -> Box
<Error
+ Send
+ Sync
+ 'a
> {
171 #[stable(feature = "rust1", since = "1.0.0")]
172 impl From
<String
> for Box
<Error
+ Send
+ Sync
> {
173 fn from(err
: String
) -> Box
<Error
+ Send
+ Sync
> {
175 struct StringError(String
);
177 impl Error
for StringError
{
178 fn description(&self) -> &str { &self.0 }
181 impl Display
for StringError
{
182 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
183 Display
::fmt(&self.0, f
)
187 Box
::new(StringError(err
))
191 #[stable(feature = "string_box_error", since = "1.7.0")]
192 impl From
<String
> for Box
<Error
> {
193 fn from(str_err
: String
) -> Box
<Error
> {
194 let err1
: Box
<Error
+ Send
+ Sync
> = From
::from(str_err
);
195 let err2
: Box
<Error
> = err1
;
200 #[stable(feature = "rust1", since = "1.0.0")]
201 impl<'a
, 'b
> From
<&'b
str> for Box
<Error
+ Send
+ Sync
+ 'a
> {
202 fn from(err
: &'b
str) -> Box
<Error
+ Send
+ Sync
+ 'a
> {
203 From
::from(String
::from(err
))
207 #[stable(feature = "string_box_error", since = "1.7.0")]
208 impl<'a
> From
<&'a
str> for Box
<Error
> {
209 fn from(err
: &'a
str) -> Box
<Error
> {
210 From
::from(String
::from(err
))
214 #[stable(feature = "rust1", since = "1.0.0")]
215 impl Error
for str::ParseBoolError
{
216 fn description(&self) -> &str { "failed to parse bool" }
219 #[stable(feature = "rust1", since = "1.0.0")]
220 impl Error
for str::Utf8Error
{
221 fn description(&self) -> &str {
222 "invalid utf-8: corrupt contents"
226 #[stable(feature = "rust1", since = "1.0.0")]
227 impl Error
for num
::ParseIntError
{
228 fn description(&self) -> &str {
233 #[unstable(feature = "try_from", issue = "33417")]
234 impl Error
for num
::TryFromIntError
{
235 fn description(&self) -> &str {
240 #[stable(feature = "rust1", since = "1.0.0")]
241 impl Error
for num
::ParseFloatError
{
242 fn description(&self) -> &str {
247 #[stable(feature = "rust1", since = "1.0.0")]
248 impl Error
for string
::FromUtf8Error
{
249 fn description(&self) -> &str {
254 #[stable(feature = "rust1", since = "1.0.0")]
255 impl Error
for string
::FromUtf16Error
{
256 fn description(&self) -> &str {
261 #[stable(feature = "str_parse_error2", since = "1.8.0")]
262 impl Error
for string
::ParseError
{
263 fn description(&self) -> &str {
268 #[stable(feature = "decode_utf16", since = "1.9.0")]
269 impl Error
for char::DecodeUtf16Error
{
270 fn description(&self) -> &str {
271 "unpaired surrogate found"
275 #[stable(feature = "box_error", since = "1.7.0")]
276 impl<T
: Error
> Error
for Box
<T
> {
277 fn description(&self) -> &str {
278 Error
::description(&**self)
281 fn cause(&self) -> Option
<&Error
> {
282 Error
::cause(&**self)
286 #[stable(feature = "fmt_error", since = "1.11.0")]
287 impl Error
for fmt
::Error
{
288 fn description(&self) -> &str {
289 "an error occurred when formatting an argument"
293 #[unstable(feature = "try_borrow", issue = "35070")]
294 impl<'a
, T
: ?Sized
+ Reflect
> Error
for cell
::BorrowError
<'a
, T
> {
295 fn description(&self) -> &str {
296 "already mutably borrowed"
300 #[unstable(feature = "try_borrow", issue = "35070")]
301 impl<'a
, T
: ?Sized
+ Reflect
> Error
for cell
::BorrowMutError
<'a
, T
> {
302 fn description(&self) -> &str {
307 // copied from any.rs
308 impl Error
+ '
static {
309 /// Returns true if the boxed type is the same as `T`
310 #[stable(feature = "error_downcast", since = "1.3.0")]
312 pub fn is
<T
: Error
+ '
static>(&self) -> bool
{
313 // Get TypeId of the type this function is instantiated with
314 let t
= TypeId
::of
::<T
>();
316 // Get TypeId of the type in the trait object
317 let boxed
= self.type_id();
319 // Compare both TypeIds on equality
323 /// Returns some reference to the boxed value if it is of type `T`, or
324 /// `None` if it isn't.
325 #[stable(feature = "error_downcast", since = "1.3.0")]
327 pub fn downcast_ref
<T
: Error
+ '
static>(&self) -> Option
<&T
> {
330 // Get the raw representation of the trait object
331 let to
: TraitObject
= transmute(self);
333 // Extract the data pointer
334 Some(&*(to
.data
as *const T
))
341 /// Returns some mutable reference to the boxed value if it is of type `T`, or
342 /// `None` if it isn't.
343 #[stable(feature = "error_downcast", since = "1.3.0")]
345 pub fn downcast_mut
<T
: Error
+ '
static>(&mut self) -> Option
<&mut T
> {
348 // Get the raw representation of the trait object
349 let to
: TraitObject
= transmute(self);
351 // Extract the data pointer
352 Some(&mut *(to
.data
as *const T
as *mut T
))
360 impl Error
+ '
static + Send
{
361 /// Forwards to the method defined on the type `Any`.
362 #[stable(feature = "error_downcast", since = "1.3.0")]
364 pub fn is
<T
: Error
+ '
static>(&self) -> bool
{
365 <Error
+ '
static>::is
::<T
>(self)
368 /// Forwards to the method defined on the type `Any`.
369 #[stable(feature = "error_downcast", since = "1.3.0")]
371 pub fn downcast_ref
<T
: Error
+ '
static>(&self) -> Option
<&T
> {
372 <Error
+ '
static>::downcast_ref
::<T
>(self)
375 /// Forwards to the method defined on the type `Any`.
376 #[stable(feature = "error_downcast", since = "1.3.0")]
378 pub fn downcast_mut
<T
: Error
+ '
static>(&mut self) -> Option
<&mut T
> {
379 <Error
+ '
static>::downcast_mut
::<T
>(self)
383 impl Error
+ '
static + Send
+ Sync
{
384 /// Forwards to the method defined on the type `Any`.
385 #[stable(feature = "error_downcast", since = "1.3.0")]
387 pub fn is
<T
: Error
+ '
static>(&self) -> bool
{
388 <Error
+ '
static>::is
::<T
>(self)
391 /// Forwards to the method defined on the type `Any`.
392 #[stable(feature = "error_downcast", since = "1.3.0")]
394 pub fn downcast_ref
<T
: Error
+ '
static>(&self) -> Option
<&T
> {
395 <Error
+ '
static>::downcast_ref
::<T
>(self)
398 /// Forwards to the method defined on the type `Any`.
399 #[stable(feature = "error_downcast", since = "1.3.0")]
401 pub fn downcast_mut
<T
: Error
+ '
static>(&mut self) -> Option
<&mut T
> {
402 <Error
+ '
static>::downcast_mut
::<T
>(self)
408 #[stable(feature = "error_downcast", since = "1.3.0")]
409 /// Attempt to downcast the box to a concrete type.
410 pub fn downcast
<T
: Error
+ '
static>(self: Box
<Self>) -> Result
<Box
<T
>, Box
<Error
>> {
413 // Get the raw representation of the trait object
414 let raw
= Box
::into_raw(self);
415 let to
: TraitObject
=
416 transmute
::<*mut Error
, TraitObject
>(raw
);
418 // Extract the data pointer
419 Ok(Box
::from_raw(to
.data
as *mut T
))
429 #[stable(feature = "error_downcast", since = "1.3.0")]
430 /// Attempt to downcast the box to a concrete type.
431 pub fn downcast
<T
: Error
+ '
static>(self: Box
<Self>)
432 -> Result
<Box
<T
>, Box
<Error
+ Send
>> {
433 let err
: Box
<Error
> = self;
434 <Error
>::downcast(err
).map_err(|s
| unsafe {
435 // reapply the Send marker
436 transmute
::<Box
<Error
>, Box
<Error
+ Send
>>(s
)
441 impl Error
+ Send
+ Sync
{
443 #[stable(feature = "error_downcast", since = "1.3.0")]
444 /// Attempt to downcast the box to a concrete type.
445 pub fn downcast
<T
: Error
+ '
static>(self: Box
<Self>)
446 -> Result
<Box
<T
>, Box
<Self>> {
447 let err
: Box
<Error
> = self;
448 <Error
>::downcast(err
).map_err(|s
| unsafe {
449 // reapply the Send+Sync marker
450 transmute
::<Box
<Error
>, Box
<Error
+ Send
+ Sync
>>(s
)
461 #[derive(Debug, PartialEq)]
463 #[derive(Debug, PartialEq)]
466 impl fmt
::Display
for A
{
467 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
471 impl fmt
::Display
for B
{
472 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
478 fn description(&self) -> &str { "A-desc" }
481 fn description(&self) -> &str { "A-desc" }
487 let mut a
= &mut a
as &mut (Error
+ '
static);
488 assert_eq
!(a
.downcast_ref
::<A
>(), Some(&A
));
489 assert_eq
!(a
.downcast_ref
::<B
>(), None
);
490 assert_eq
!(a
.downcast_mut
::<A
>(), Some(&mut A
));
491 assert_eq
!(a
.downcast_mut
::<B
>(), None
);
493 let a
: Box
<Error
> = Box
::new(A
);
494 match a
.downcast
::<B
>() {
495 Ok(..) => panic
!("expected error"),
496 Err(e
) => assert_eq
!(*e
.downcast
::<A
>().unwrap(), A
),