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

Commit 23586d7

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 c9b3757 commit 23586d7

File tree

6 files changed

+32
-74
lines changed

6 files changed

+32
-74
lines changed

CHANGELOG.md

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

3+
- [Shrink the size of `Error` to a pointer](https://github.com/rust-lang-nursery/error-chain/pull/225)
4+
35
# 0.11.0
46

57
- Change last rust version supported to 1.14

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 & 38 deletions
This file was deleted.

src/error_chain.rs

Lines changed: 19 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,15 +163,15 @@ macro_rules! impl_error_chain_processed {
170163

171164
impl ::std::error::Error for $error_name {
172165
fn description(&self) -> &str {
173-
self.0.description()
166+
(self.0).0.description()
174167
}
175168

176169
#[allow(unknown_lints, unused_doc_comment)]
177170
fn cause(&self) -> Option<&::std::error::Error> {
178-
match self.1.next_error {
171+
match (self.0).1.next_error {
179172
Some(ref c) => Some(&**c),
180173
None => {
181-
match self.0 {
174+
match (self.0).0 {
182175
$(
183176
$(#[$meta_foreign_links])*
184177
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
@@ -194,18 +187,19 @@ macro_rules! impl_error_chain_processed {
194187

195188
impl ::std::fmt::Display for $error_name {
196189
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
197-
::std::fmt::Display::fmt(&self.0, f)
190+
::std::fmt::Display::fmt(&(self.0).0, f)
198191
}
199192
}
200193

201194
$(
202195
$(#[$meta_links])*
203196
impl From<$link_error_path> for $error_name {
204197
fn from(e: $link_error_path) -> Self {
205-
$error_name(
198+
let e = *e.0;
199+
$error_name(Box::new((
206200
$error_kind_name::$link_variant(e.0),
207201
e.1,
208-
)
202+
)))
209203
}
210204
}
211205
) *
@@ -243,7 +237,7 @@ macro_rules! impl_error_chain_processed {
243237
type Target = $error_kind_name;
244238

245239
fn deref(&self) -> &Self::Target {
246-
&self.0
240+
&(self.0).0
247241
}
248242
}
249243

@@ -305,7 +299,7 @@ macro_rules! impl_error_chain_processed {
305299

306300
impl From<$error_name> for $error_kind_name {
307301
fn from(e: $error_name) -> Self {
308-
e.0
302+
(e.0).0
309303
}
310304
}
311305

@@ -428,13 +422,13 @@ macro_rules! impl_extract_backtrace {
428422
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
429423
-> Option<::std::sync::Arc<$crate::Backtrace>> {
430424
if let Some(e) = e.downcast_ref::<$error_name>() {
431-
return e.1.backtrace.clone();
425+
return (e.0).1.backtrace.clone();
432426
}
433427
$(
434428
$( #[$meta_links] )*
435429
{
436430
if let Some(e) = e.downcast_ref::<$link_error_path>() {
437-
return e.1.backtrace.clone();
431+
return (e.0).1.backtrace.clone();
438432
}
439433
}
440434
) *

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: 3 additions & 3 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
}

0 commit comments

Comments
 (0)