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

Commit

Permalink
Shrink the size of all Error types
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Sep 24, 2017
1 parent c9b3757 commit f9c26a0
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 69 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- [Shrink the size of `Error` to a pointer](https://github.com/rust-lang-nursery/error-chain/pull/225)

# 0.11.0

- Change last rust version supported to 1.14
Expand Down
6 changes: 3 additions & 3 deletions examples/chain_err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ fn load_config(rel_path: &str) -> Result<()> {

/// Launch the service.
fn launch(rel_path: &str) -> Result<()> {
load_config(rel_path).map_err(|e| match e {
e @ Error(ErrorKind::ConfigLoad(_), _) => {
load_config(rel_path).map_err(|e| match *e.kind() {
ErrorKind::ConfigLoad(_) => {
e.chain_err(|| LaunchStage::ConfigLoad)
}
e => e.chain_err(|| "Unknown failure"),
_ => e.chain_err(|| "Unknown failure"),
})
}

Expand Down
38 changes: 0 additions & 38 deletions examples/size.rs

This file was deleted.

44 changes: 19 additions & 25 deletions src/error_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,13 @@ macro_rules! impl_error_chain_processed {
/// - a backtrace, generated when the error is created.
/// - an error chain, used for the implementation of `Error::cause()`.
#[derive(Debug)]
pub struct $error_name(
// The members must be `pub` for `links`.
/// The kind of the error.
pub $error_kind_name,
/// Contains the error chain and the backtrace.
#[doc(hidden)]
pub $crate::State,
);
pub struct $error_name(pub Box<($error_kind_name, $crate::State)>);

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

fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
$error_name(kind, state)
$error_name(Box::new((kind, state)))
}

fn from_kind(kind: Self::ErrorKind) -> Self {
Expand Down Expand Up @@ -120,10 +113,10 @@ macro_rules! impl_error_chain_processed {
impl $error_name {
/// Constructs an error from a kind, and generates a backtrace.
pub fn from_kind(kind: $error_kind_name) -> $error_name {
$error_name(
$error_name(Box::new((
kind,
$crate::State::default(),
)
)))
}

/// Constructs a chained error from another error and a kind, and generates a backtrace.
Expand All @@ -140,15 +133,15 @@ macro_rules! impl_error_chain_processed {
-> $error_name
where K: Into<$error_kind_name>
{
$error_name(
$error_name(Box::new((
kind.into(),
$crate::State::new::<$error_name>(error, ),
)
)))
}

/// Returns the kind of the error.
pub fn kind(&self) -> &$error_kind_name {
&self.0
&(self.0).0
}

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

/// Returns the backtrace associated with this error.
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
self.1.backtrace()
(self.0).1.backtrace()
}

/// Extends the error chain with a new entry.
Expand All @@ -170,15 +163,15 @@ macro_rules! impl_error_chain_processed {

impl ::std::error::Error for $error_name {
fn description(&self) -> &str {
self.0.description()
(self.0).0.description()
}

#[allow(unknown_lints, unused_doc_comment)]
fn cause(&self) -> Option<&::std::error::Error> {
match self.1.next_error {
match (self.0).1.next_error {
Some(ref c) => Some(&**c),
None => {
match self.0 {
match (self.0).0 {
$(
$(#[$meta_foreign_links])*
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
Expand All @@ -194,18 +187,19 @@ macro_rules! impl_error_chain_processed {

impl ::std::fmt::Display for $error_name {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::std::fmt::Display::fmt(&self.0, f)
::std::fmt::Display::fmt(&(self.0).0, f)
}
}

$(
$(#[$meta_links])*
impl From<$link_error_path> for $error_name {
fn from(e: $link_error_path) -> Self {
$error_name(
let e = *e.0;
$error_name(Box::new((
$error_kind_name::$link_variant(e.0),
e.1,
)
)))
}
}
) *
Expand Down Expand Up @@ -243,7 +237,7 @@ macro_rules! impl_error_chain_processed {
type Target = $error_kind_name;

fn deref(&self) -> &Self::Target {
&self.0
&(self.0).0
}
}

Expand Down Expand Up @@ -305,7 +299,7 @@ macro_rules! impl_error_chain_processed {

impl From<$error_name> for $error_kind_name {
fn from(e: $error_name) -> Self {
e.0
(e.0).0
}
}

Expand Down Expand Up @@ -428,13 +422,13 @@ macro_rules! impl_extract_backtrace {
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
-> Option<::std::sync::Arc<$crate::Backtrace>> {
if let Some(e) = e.downcast_ref::<$error_name>() {
return e.1.backtrace.clone();
return (e.0).1.backtrace.clone();
}
$(
$( #[$meta_links] )*
{
if let Some(e) = e.downcast_ref::<$link_error_path>() {
return e.1.backtrace.clone();
return (e.0).1.backtrace.clone();
}
}
) *
Expand Down
6 changes: 3 additions & 3 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ fn error_chain_err() {
let base = Error::from(ErrorKind::Test);
let ext = base.chain_err(|| "Test passes");

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

// Tuples look nice when matching errors
match Error::from("Test") {
Error(ErrorKind::Msg(_), _) => {},
match *Error::from("Test").kind() {
ErrorKind::Msg(_) => {},
_ => {},
}
}
Expand Down

0 comments on commit f9c26a0

Please sign in to comment.