Also move Error and Chain to get usable paths in diagnostics

This commit is contained in:
David Tolnay 2019-10-21 11:22:04 -07:00
parent fc44da4836
commit 27fcdd42a0
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 41 additions and 39 deletions

View File

@ -1,5 +1,6 @@
use crate::backtrace::Backtrace; use crate::backtrace::Backtrace;
use crate::context::ContextError; use crate::context::ContextError;
use crate::{Chain, Error};
use std::any::TypeId; use std::any::TypeId;
use std::error::Error as StdError; use std::error::Error as StdError;
use std::fmt::{self, Debug, Display}; use std::fmt::{self, Debug, Display};
@ -7,20 +8,6 @@ use std::mem::{self, ManuallyDrop};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
/// error type does not provide one.
/// - `Error` is represented as a narrow pointer &mdash; exactly one word in
/// size instead of two.
pub struct Error {
inner: ManuallyDrop<Box<ErrorImpl<()>>>,
}
impl Error { impl Error {
/// Create a new error object from any error type. /// Create a new error object from any error type.
/// ///
@ -405,7 +392,7 @@ where
// repr C to ensure that `E` remains in the final position // repr C to ensure that `E` remains in the final position
#[repr(C)] #[repr(C)]
struct ErrorImpl<E> { pub(crate) struct ErrorImpl<E> {
vtable: &'static ErrorVTable, vtable: &'static ErrorVTable,
type_id: TypeId, type_id: TypeId,
backtrace: Option<Backtrace>, backtrace: Option<Backtrace>,
@ -578,29 +565,6 @@ impl From<Error> for Box<dyn StdError + 'static> {
} }
} }
/// Iterator of a chain of source errors.
///
/// This type is the iterator returned by [`Error::chain`].
///
/// # Example
///
/// ```
/// use anyhow::Error;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
/// for cause in error.chain() {
/// if let Some(io_error) = cause.downcast_ref::<io::Error>() {
/// return Some(io_error.kind());
/// }
/// }
/// None
/// }
/// ```
pub struct Chain<'a> {
next: Option<&'a (dyn StdError + 'static)>,
}
impl<'a> Iterator for Chain<'a> { impl<'a> Iterator for Chain<'a> {
type Item = &'a (dyn StdError + 'static); type Item = &'a (dyn StdError + 'static);

View File

@ -183,9 +183,47 @@ mod kind;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet"); compile_error!("no_std support is not implemented yet");
use crate::error::ErrorImpl;
use std::error::Error as StdError;
use std::fmt::Display; use std::fmt::Display;
use std::mem::ManuallyDrop;
pub use crate::error::{Chain, Error}; /// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
/// error type does not provide one.
/// - `Error` is represented as a narrow pointer &mdash; exactly one word in
/// size instead of two.
pub struct Error {
inner: ManuallyDrop<Box<ErrorImpl<()>>>,
}
/// Iterator of a chain of source errors.
///
/// This type is the iterator returned by [`Error::chain`].
///
/// # Example
///
/// ```
/// use anyhow::Error;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
/// for cause in error.chain() {
/// if let Some(io_error) = cause.downcast_ref::<io::Error>() {
/// return Some(io_error.kind());
/// }
/// }
/// None
/// }
/// ```
pub struct Chain<'a> {
next: Option<&'a (dyn StdError + 'static)>,
}
/// `Result<T, Error>` /// `Result<T, Error>`
/// ///