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

Commit f3020b8

Browse files
committed
Shrink the size of all Error types
This commit improves the in-memory size of `Error` from 7 pointers to 1 pointer. Errors are in general relatively rare in applications and having a huge error type ends up generating lots of instructions for moves and such, so this PR optimizes for size and passing around errors rather than creating errors.
1 parent 92a54ba commit f3020b8

File tree

6 files changed

+36
-68
lines changed

6 files changed

+36
-68
lines changed

CHANGELOG.md

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

33
- [Remove `impl Deref<Kind> for Error`](https://github.com/rust-lang-nursery/error-chain/pull/192)
4+
- [Shrink the size of `Error` to a pointer](https://github.com/rust-lang-nursery/error-chain/pull/225)
45

56
# 0.11.0
67

examples/chain_err.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ fn load_config(rel_path: &str) -> Result<()> {
5353

5454
/// Launch the service.
5555
fn launch(rel_path: &str) -> Result<()> {
56-
load_config(rel_path).map_err(|e| match e {
57-
e @ Error(ErrorKind::ConfigLoad(_), _) => {
56+
load_config(rel_path).map_err(|e| match *e.kind() {
57+
ErrorKind::ConfigLoad(_) => {
5858
e.chain_err(|| LaunchStage::ConfigLoad)
5959
}
60-
e => e.chain_err(|| "Unknown failure"),
60+
_ => e.chain_err(|| "Unknown failure"),
6161
})
6262
}
6363

examples/size.rs

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/error_chain.rs

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,13 @@ macro_rules! impl_error_chain_processed {
6565
/// - a backtrace, generated when the error is created.
6666
/// - an error chain, used for the implementation of `Error::cause()`.
6767
#[derive(Debug)]
68-
pub struct $error_name(
69-
// The members must be `pub` for `links`.
70-
/// The kind of the error.
71-
pub $error_kind_name,
72-
/// Contains the error chain and the backtrace.
73-
#[doc(hidden)]
74-
pub $crate::State,
75-
);
68+
pub struct $error_name(pub Box<($error_kind_name, $crate::State)>);
7669

7770
impl $crate::ChainedError for $error_name {
7871
type ErrorKind = $error_kind_name;
7972

8073
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
81-
$error_name(kind, state)
74+
$error_name(Box::new((kind, state)))
8275
}
8376

8477
fn from_kind(kind: Self::ErrorKind) -> Self {
@@ -120,10 +113,10 @@ macro_rules! impl_error_chain_processed {
120113
impl $error_name {
121114
/// Constructs an error from a kind, and generates a backtrace.
122115
pub fn from_kind(kind: $error_kind_name) -> $error_name {
123-
$error_name(
116+
$error_name(Box::new((
124117
kind,
125118
$crate::State::default(),
126-
)
119+
)))
127120
}
128121

129122
/// Constructs a chained error from another error and a kind, and generates a backtrace.
@@ -140,15 +133,15 @@ macro_rules! impl_error_chain_processed {
140133
-> $error_name
141134
where K: Into<$error_kind_name>
142135
{
143-
$error_name(
136+
$error_name(Box::new((
144137
kind.into(),
145138
$crate::State::new::<$error_name>(error, ),
146-
)
139+
)))
147140
}
148141

149142
/// Returns the kind of the error.
150143
pub fn kind(&self) -> &$error_kind_name {
151-
&self.0
144+
&(self.0).0
152145
}
153146

154147
/// Iterates over the error chain.
@@ -158,7 +151,7 @@ macro_rules! impl_error_chain_processed {
158151

159152
/// Returns the backtrace associated with this error.
160153
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
161-
self.1.backtrace()
154+
(self.0).1.backtrace()
162155
}
163156

164157
/// Extends the error chain with a new entry.
@@ -170,7 +163,7 @@ macro_rules! impl_error_chain_processed {
170163
/// A short description of the error.
171164
/// This method is identical to [`Error::description()`](https://doc.rust-lang.org/nightly/std/error/trait.Error.html#tymethod.description)
172165
pub fn description(&self) -> &str {
173-
self.0.description()
166+
(self.0).0.description()
174167
}
175168
}
176169

@@ -181,10 +174,10 @@ macro_rules! impl_error_chain_processed {
181174

182175
#[allow(unknown_lints, unused_doc_comment)]
183176
fn cause(&self) -> Option<&::std::error::Error> {
184-
match self.1.next_error {
177+
match (self.0).1.next_error {
185178
Some(ref c) => Some(&**c),
186179
None => {
187-
match self.0 {
180+
match (self.0).0 {
188181
$(
189182
$(#[$meta_foreign_links])*
190183
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
@@ -200,18 +193,19 @@ macro_rules! impl_error_chain_processed {
200193

201194
impl ::std::fmt::Display for $error_name {
202195
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
203-
::std::fmt::Display::fmt(&self.0, f)
196+
::std::fmt::Display::fmt(&(self.0).0, f)
204197
}
205198
}
206199

207200
$(
208201
$(#[$meta_links])*
209202
impl From<$link_error_path> for $error_name {
210203
fn from(e: $link_error_path) -> Self {
211-
$error_name(
204+
let e = *e.0;
205+
$error_name(Box::new((
212206
$error_kind_name::$link_variant(e.0),
213207
e.1,
214-
)
208+
)))
215209
}
216210
}
217211
) *
@@ -245,7 +239,6 @@ macro_rules! impl_error_chain_processed {
245239
}
246240
}
247241

248-
249242
// The ErrorKind type
250243
// --------------
251244

@@ -303,7 +296,7 @@ macro_rules! impl_error_chain_processed {
303296

304297
impl From<$error_name> for $error_kind_name {
305298
fn from(e: $error_name) -> Self {
306-
e.0
299+
(e.0).0
307300
}
308301
}
309302

@@ -425,13 +418,13 @@ macro_rules! impl_extract_backtrace {
425418
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
426419
-> Option<$crate::InternalBacktrace> {
427420
if let Some(e) = e.downcast_ref::<$error_name>() {
428-
return Some(e.1.backtrace.clone());
421+
return Some((e.0).1.backtrace.clone());
429422
}
430423
$(
431424
$( #[$meta_links] )*
432425
{
433426
if let Some(e) = e.downcast_ref::<$link_error_path>() {
434-
return Some(e.1.backtrace.clone());
427+
return Some((e.0).1.backtrace.clone());
435428
}
436429
}
437430
) *

src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,9 @@
345345
//! }
346346
//! }
347347
//!
348-
//! match Error::from("error!") {
349-
//! Error(ErrorKind::InvalidToolchainName(_), _) => { }
350-
//! Error(ErrorKind::Msg(_), _) => { }
348+
//! match *Error::from("error!").kind() {
349+
//! ErrorKind::InvalidToolchainName(_) => { }
350+
//! ErrorKind::Msg(_) => { }
351351
//! _ => { }
352352
//! }
353353
//! # }
@@ -377,8 +377,8 @@
377377
//!
378378
//!
379379
//! # fn main() {
380-
//! match app::Error::from("error!") {
381-
//! app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { }
380+
//! match *app::Error::from("error!").kind() {
381+
//! app::ErrorKind::Utils(utils::ErrorKind::BadStuff) => { }
382382
//! _ => { }
383383
//! }
384384
//! # }

tests/tests.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ fn error_chain_err() {
255255
let base = Error::from(ErrorKind::Test);
256256
let ext = base.chain_err(|| "Test passes");
257257

258-
if let Error(ErrorKind::Msg(_), _) = ext {
258+
if let ErrorKind::Msg(_) = *ext.kind() {
259259
// pass
260260
} else {
261261
panic!("The error should be wrapped. {:?}", ext);
@@ -484,8 +484,8 @@ fn error_patterns() {
484484
}
485485

486486
// Tuples look nice when matching errors
487-
match Error::from("Test") {
488-
Error(ErrorKind::Msg(_), _) => {},
487+
match *Error::from("Test").kind() {
488+
ErrorKind::Msg(_) => {},
489489
_ => {},
490490
}
491491
}
@@ -500,8 +500,12 @@ fn result_match() {
500500

501501
match ok() {
502502
Ok(()) => {},
503-
Err(Error(ErrorKind::Msg(_), _)) => {},
504-
Err(..) => {},
503+
Err(e) => {
504+
match *e.kind() {
505+
ErrorKind::Msg(_) => {}
506+
_ => {}
507+
}
508+
}
505509
}
506510
}
507511

0 commit comments

Comments
 (0)