Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit 82a27f3

Browse files
committed
Add boxed-error feature.
Fixes #44.
1 parent 5da59c2 commit 82a27f3

File tree

6 files changed

+108
-41
lines changed

6 files changed

+108
-41
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ env:
3030
global:
3131
- secure: ncxJbvJM1vCZfcEftjsFKJMxxhKLgWKaR8Go9AMo0VB5fB2XVW/6NYO5bQEEYpOf1Nc/+2FbI2+Dkz0S/mJpUcNSfBgablCHgwU2sHse7KsoaqfHj2mf1E3exjzSHoP96hPGicC5zAjSXFjCgJPOUSGqqRaJ7z5AsJLhJT6LuK7QpvwPBZzklUN8T+n1sVmws8TNmRIbaniq/q6wYHANHcy6Dl59dx4sKwniUGiZdUhCiddVpoxbECSxc0A8mN2pk7/aW+WGxK3goBs5ZF7+JXF318F62pDcXQmR5CX6WdpenIcJ25g1Vg1WhQ4Ifpe17CN0bfxV8ShuzrQUThCDMffZCo9XySBtODdEowwK1UIpjnFLfIxjOs45Cd8o3tM2j0CfvtnjOz6BCdUU0qiwNPPNx0wFkx3ZiOfSh+FhBhvyPM12HN2tdN0esgVBItFmEci+sSIIXqjVL6DNiu5zTjbu0bs6COwlUWdmL6vmsZtq5tl7Cno9+C3szxRVAkShGydd04l9NYjqNEzTa1EPG50OsnVRKGdRiFzSxhc3BWExNKvcQ4v867t6/PpPkW6s4oXmYI3+De+8O7ExWc6a4alcrDXKlMs5fCb5Pcd4Ju9kowcjkoJo5yf2wW3Ox5R8SJpaEEpvyhx5O/qtIxjhHNzeo8Wsr/6gdNDv20r91TI=
3232
matrix:
33-
- FEATURES=--features=backtrace
3433
- FEATURES=--no-default-features
34+
- FEATURES=--no-default-features --features=boxed-error
35+
- FEATURES=--all-features

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- New `Variant(Error) #[attrs]` for `links` and `foreign_links`.
44
- Hide implementation details from the doc.
5+
- Add `boxed-error` feature (#69).
56

67
# 0.6.1
78

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ repository = "https://github.com/brson/error-chain"
1515
license = "MIT/Apache-2.0"
1616

1717
[features]
18-
default = ["backtrace", "example_generated"]
19-
example_generated = []
18+
default = ["backtrace", "example-generated"]
19+
example-generated = []
20+
boxed-error = []
2021

2122
[dependencies]
2223
backtrace = { version = "0.3", optional = true }

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ provides a few unique features:
2121

2222
See the [quickstart example](examples/quickstart.rs).
2323

24+
## Features
25+
26+
- `backtrace`: generates backtraces on error creation.
27+
- `boxed-error`: the error is boxed (see #44).
28+
- `example-generated`: generates the example in the documentation (should be
29+
disabled).
30+
2431
## License
2532

2633
MIT/Apache-2.0

src/error_chain.rs

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,12 @@ macro_rules! error_chain_processed {
5050
}
5151

5252
) => {
53-
/// The Error type.
54-
///
55-
/// This struct is made of three things:
56-
///
57-
/// - an `ErrorKind` which is used to determine the type of the error.
58-
/// - a backtrace, generated when the error is created.
59-
/// - an error chain, used for the implementation of `Error::cause()`.
53+
define_error!($error_name, Inner);
54+
55+
/// Separated for the `boxed-error` feature.
6056
#[derive(Debug)]
61-
pub struct $error_name {
57+
#[doc(hidden)]
58+
pub struct Inner {
6259
// The members must be `pub` for `links`.
6360
/// The kind of the error.
6461
#[doc(hidden)]
@@ -68,16 +65,17 @@ macro_rules! error_chain_processed {
6865
pub state: $crate::State,
6966
}
7067

68+
impl Inner {
69+
/// Used in From<ChainedError>.
70+
pub fn into_raw(self) -> ($error_kind_name, $crate::State) {
71+
(self.kind, self.state)
72+
}
73+
}
74+
7175
impl $crate::ChainedError for $error_name {
7276
type ErrorKind = $error_kind_name;
7377

74-
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
75-
$error_name {
76-
kind: kind,
77-
state: state,
78-
}
79-
}
80-
78+
impl_chained_error_new!($error_name, $error_kind_name);
8179
impl_extract_backtrace!($error_name
8280
$error_kind_name
8381
$([$link_error_path, $(#[$meta_links])*])*);
@@ -87,15 +85,13 @@ macro_rules! error_chain_processed {
8785
impl $error_name {
8886
/// Constructs an error from a kind, and generates a backtrace.
8987
pub fn from_kind(kind: $error_kind_name) -> $error_name {
90-
$error_name {
91-
kind: kind,
92-
state: $crate::State::default(),
93-
}
88+
use $crate::ChainedError;
89+
Self::new(kind, $crate::State::default())
9490
}
9591

9692
/// Returns the kind of the error.
9793
pub fn kind(&self) -> &$error_kind_name {
98-
&self.kind
94+
&self.0.kind
9995
}
10096

10197
/// Iterates over the error chain.
@@ -105,20 +101,20 @@ macro_rules! error_chain_processed {
105101

106102
/// Returns the backtrace associated with this error.
107103
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
108-
self.state.backtrace()
104+
self.0.state.backtrace()
109105
}
110106
}
111107

112108
impl ::std::error::Error for $error_name {
113109
fn description(&self) -> &str {
114-
self.kind.description()
110+
self.0.kind.description()
115111
}
116112

117113
fn cause(&self) -> Option<&::std::error::Error> {
118-
match self.state.next_error {
114+
match self.0.state.next_error {
119115
Some(ref c) => Some(&**c),
120116
None => {
121-
match self.kind {
117+
match self.0.kind {
122118
$(
123119
$(#[$meta_foreign_links])*
124120
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
@@ -134,18 +130,17 @@ macro_rules! error_chain_processed {
134130

135131
impl ::std::fmt::Display for $error_name {
136132
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
137-
::std::fmt::Display::fmt(&self.kind, f)
133+
::std::fmt::Display::fmt(&self.0.kind, f)
138134
}
139135
}
140136

141137
$(
142138
$(#[$meta_links])*
143139
impl From<$link_error_path> for $error_name {
144140
fn from(e: $link_error_path) -> Self {
145-
$error_name {
146-
kind: $error_kind_name::$link_variant(e.kind),
147-
state: e.state,
148-
}
141+
use $crate::ChainedError;
142+
let (kind, state) = e.0.into_raw();
143+
Self::new($error_kind_name::$link_variant(kind), state)
149144
}
150145
}
151146
) *
@@ -183,7 +178,7 @@ macro_rules! error_chain_processed {
183178
type Target = $error_kind_name;
184179

185180
fn deref(&self) -> &Self::Target {
186-
&self.kind
181+
&self.0.kind
187182
}
188183
}
189184

@@ -245,7 +240,7 @@ macro_rules! error_chain_processed {
245240

246241
impl From<$error_name> for $error_kind_name {
247242
fn from(e: $error_name) -> Self {
248-
e.kind
243+
e.0.kind
249244
}
250245
}
251246
};
@@ -332,13 +327,13 @@ macro_rules! impl_extract_backtrace {
332327
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
333328
-> Option<Option<::std::sync::Arc<$crate::Backtrace>>> {
334329
if let Some(e) = e.downcast_ref::<$error_name>() {
335-
return Some(e.state.backtrace.clone());
330+
return Some(e.0.state.backtrace.clone());
336331
}
337332
$(
338333
$( #[$meta_links] )*
339334
{
340335
if let Some(e) = e.downcast_ref::<$link_error_path>() {
341-
return Some(e.state.backtrace.clone());
336+
return Some(e.0.state.backtrace.clone());
342337
}
343338
}
344339
) *
@@ -360,3 +355,65 @@ macro_rules! impl_extract_backtrace {
360355
$error_kind_name: ident
361356
$([$link_error_path: path, $(#[$meta_links: meta])*])*) => {}
362357
}
358+
359+
#[macro_export]
360+
#[doc(hidden)]
361+
#[cfg(feature = "boxed-error")]
362+
macro_rules! impl_chained_error_new {
363+
($error_name: ident, $error_kind_name: ident) => {
364+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
365+
$error_name(Box::new(Inner {
366+
kind: kind,
367+
state: state,
368+
}))
369+
}
370+
}
371+
}
372+
373+
#[macro_export]
374+
#[doc(hidden)]
375+
#[cfg(not(feature = "boxed-error"))]
376+
macro_rules! impl_chained_error_new {
377+
($error_name: ident, $error_kind_name: ident) => {
378+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
379+
$error_name(Inner {
380+
kind: kind,
381+
state: state,
382+
})
383+
}
384+
}
385+
}
386+
387+
#[macro_export]
388+
#[doc(hidden)]
389+
#[cfg(feature = "boxed-error")]
390+
macro_rules! define_error {
391+
($error_name: ident, $inner_name: ident) => {
392+
/// The Error type.
393+
///
394+
/// This struct is made of three things:
395+
///
396+
/// - an `ErrorKind` which is used to determine the type of the error.
397+
/// - a backtrace, generated when the error is created.
398+
/// - an error chain, used for the implementation of `Error::cause()`.
399+
#[derive(Debug)]
400+
pub struct $error_name(pub Box<$inner_name>);
401+
}
402+
}
403+
404+
#[macro_export]
405+
#[doc(hidden)]
406+
#[cfg(not(feature = "boxed-error"))]
407+
macro_rules! define_error {
408+
($error_name: ident, $inner_name: ident) => {
409+
/// The Error type.
410+
///
411+
/// This struct is made of three things:
412+
///
413+
/// - an `ErrorKind` which is used to determine the type of the error.
414+
/// - a backtrace, generated when the error is created.
415+
/// - an error chain, used for the implementation of `Error::cause()`.
416+
#[derive(Debug)]
417+
pub struct $error_name(pub $inner_name);
418+
}
419+
}

src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ pub type Backtrace = ();
269269
mod quick_error;
270270
#[macro_use]
271271
mod error_chain;
272-
#[cfg(feature = "example_generated")]
272+
#[cfg(feature = "example-generated")]
273273
pub mod example_generated;
274274

275275
/// Iterator over the error chain using the `Error::cause()` method.
@@ -320,18 +320,18 @@ pub trait ChainedError: error::Error + Send + 'static {
320320
}
321321

322322
/// Additionnal methods for `Result`, for easy interaction with this crate.
323-
pub trait ResultExt<T, E, CE: ChainedError> {
323+
pub trait ResultExt<T, E> {
324324
/// If the `Result` is an `Err` then `chain_err` evaluates the closure,
325325
/// which returns *some type that can be converted to `ErrorKind`*, boxes
326326
/// the original error to store as the cause, then returns a new error
327327
/// containing the original error.
328-
fn chain_err<F, EK>(self, callback: F) -> Result<T, CE>
328+
fn chain_err<F, EK, CE: ChainedError>(self, callback: F) -> Result<T, CE>
329329
where F: FnOnce() -> EK,
330330
EK: Into<CE::ErrorKind>;
331331
}
332332

333-
impl<T, E, CE> ResultExt<T, E, CE> for Result<T, E> where CE: ChainedError, E: error::Error + Send + 'static {
334-
fn chain_err<F, EK>(self, callback: F) -> Result<T, CE>
333+
impl<T, E> ResultExt<T, E> for Result<T, E> where E: error::Error + Send + 'static {
334+
fn chain_err<F, EK, CE: ChainedError>(self, callback: F) -> Result<T, CE>
335335
where F: FnOnce() -> EK,
336336
EK: Into<CE::ErrorKind> {
337337
self.map_err(move |e| {

0 commit comments

Comments
 (0)