Skip to content

Commit

Permalink
Implement support for no_std
Browse files Browse the repository at this point in the history
This brings no_std support to SNAFU. It now has a `std` feature which
is activated by default. To make no_std support as frictionless as
possible, SNAFU now reexports the `std::error::Error` trait as
`snafu::Error` when the feature is activated and defines its own API
compatible trait instead when it's disabled.

In order to not commit to having a publicly visible copy of the
`Error` trait in SNAFU, hiding it from the documentation allows for
SNAFU to still support all of its features, but the user never gets to
use the trait. This way SNAFU can switch out the trait at any point
with `core::error::Error` if that becomes a thing. Alternatively the
trait here can also be made visible at some point. Both of these
possibilities are not breaking, so the conservative approach with
`doc(hidden)` allows for the smoothest experience going forward.

Resolves #85
  • Loading branch information
CryZe authored and shepmaster committed Oct 8, 2019
1 parent 698aeed commit 7fbf5e3
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 97 deletions.
16 changes: 16 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ stable_test_task:
- cargo fmt --all -- --check
before_cache_script: rm -rf $CARGO_HOME/registry/index

no_std_test_task:
name: "Rust Stable (no_std)"
container:
image: rust:latest
cpu: 1
memory: 2Gi
cargo_cache:
folder: $CARGO_HOME/registry
fingerprint_script: cat Cargo.toml
setup_script:
- rustup target add thumbv6m-none-eabi
primary_test_script:
- rustc --version
- cargo build --no-default-features --target thumbv6m-none-eabi
before_cache_script: rm -rf $CARGO_HOME/registry/index

nightly_test_task:
name: "Rust Nightly"
container:
Expand Down
11 changes: 7 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ repository = "https://github.com/shepmaster/snafu"

license = "MIT OR Apache-2.0"

keywords = ["error", "ergonomic", "library"]
categories = ["rust-patterns"]
keywords = ["error", "ergonomic", "library", "no_std"]
categories = ["rust-patterns", "no-std"]

exclude = [
"/.cirrus.yml",
Expand All @@ -24,10 +24,13 @@ exclude = [
all-features = true

[features]
default = ["backtraces"]
default = ["backtraces", "std"]

# Implement the `std::error::Error` trait.
std = []

# Adds the backtrace type
backtraces = ["snafu-derive/backtraces", "backtrace"]
backtraces = ["std", "snafu-derive/backtraces", "backtrace"]

# Add conversion to `backtrace::Backtrace`
backtrace-crate = ["backtraces"]
Expand Down
2 changes: 1 addition & 1 deletion compatibility-tests/without-backtrace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ authors = ["Jake Goulding <[email protected]>"]
edition = "2018"

[dependencies]
snafu = { path = "../..", default-features = false, features = [] }
snafu = { path = "../..", default-features = false, features = ["std"] }
52 changes: 26 additions & 26 deletions snafu-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,7 +1298,7 @@ impl<'a> quote::ToTokens for ContextSelector<'a> {
let backtrace_field = match *backtrace_field {
Some(ref field) => {
let name = &field.name;
quote! { #name: std::default::Default::default(), }
quote! { #name: core::default::Default::default(), }
}
None => quote! {},
};
Expand All @@ -1308,7 +1308,7 @@ impl<'a> quote::ToTokens for ContextSelector<'a> {
.zip(user_fields)
.map(|(gen_ty, f)| {
let Field { ref ty, .. } = *f;
quote! { #gen_ty: std::convert::Into<#ty> }
quote! { #gen_ty: core::convert::Into<#ty> }
})
.chain(self.0.provided_where_clauses())
.collect();
Expand All @@ -1318,16 +1318,16 @@ impl<'a> quote::ToTokens for ContextSelector<'a> {
impl<#(#generic_names,)*> #selector_name
{
#[doc = "Consume the selector and return a `Result` with the associated error"]
#visibility fn fail<#(#original_generics_without_defaults,)* __T>(self) -> std::result::Result<__T, #parameterized_enum_name>
#visibility fn fail<#(#original_generics_without_defaults,)* __T>(self) -> core::result::Result<__T, #parameterized_enum_name>
where
#(#where_clauses),*
{
let Self { #(#names),* } = self;
let error = #enum_name::#variant_name {
#backtrace_field
#( #names: std::convert::Into::into(#names) ),*
#( #names: core::convert::Into::into(#names) ),*
};
std::result::Result::Err(error)
core::result::Result::Err(error)
}
}
}
Expand Down Expand Up @@ -1367,7 +1367,7 @@ impl<'a> quote::ToTokens for ContextSelector<'a> {
quote! {
impl#generics_list snafu::IntoError<#parameterized_enum_name> for #selector_name
where
#parameterized_enum_name: std::error::Error + snafu::ErrorCompat,
#parameterized_enum_name: snafu::Error + snafu::ErrorCompat,
#(#where_clauses),*
{
type Source = #source_ty;
Expand Down Expand Up @@ -1453,11 +1453,11 @@ impl<'a> quote::ToTokens for DisplayImpl<'a> {

stream.extend({
quote! {
impl<#(#original_generics),*> std::fmt::Display for #parameterized_enum_name
impl<#(#original_generics),*> core::fmt::Display for #parameterized_enum_name
where
#(#where_clauses),*
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
#[allow(unused_variables)]
match *self {
#(#variants_to_display)*
Expand Down Expand Up @@ -1509,13 +1509,13 @@ impl<'a> ErrorImpl<'a> {
} = *source_field;
quote! {
#enum_name::#variant_name { ref #field_name, .. } => {
std::option::Option::Some(#field_name.as_error_source())
core::option::Option::Some(#field_name.as_error_source())
}
}
}
None => {
quote! {
#enum_name::#variant_name { .. } => { std::option::Option::None }
#enum_name::#variant_name { .. } => { core::option::Option::None }
}
}
}
Expand Down Expand Up @@ -1543,7 +1543,7 @@ impl<'a> quote::ToTokens for ErrorImpl<'a> {
let variants_to_source = &self.variants_to_source();

let cause_fn = quote! {
fn cause(&self) -> Option<&dyn std::error::Error> {
fn cause(&self) -> Option<&dyn snafu::Error> {
use snafu::AsErrorSource;
match *self {
#(#variants_to_source)*
Expand All @@ -1552,7 +1552,7 @@ impl<'a> quote::ToTokens for ErrorImpl<'a> {
};

let source_fn = quote! {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
fn source(&self) -> Option<&(dyn snafu::Error + 'static)> {
use snafu::AsErrorSource;
match *self {
#(#variants_to_source)*
Expand All @@ -1562,9 +1562,9 @@ impl<'a> quote::ToTokens for ErrorImpl<'a> {

stream.extend({
quote! {
impl<#(#original_generics),*> std::error::Error for #parameterized_enum_name
impl<#(#original_generics),*> snafu::Error for #parameterized_enum_name
where
Self: std::fmt::Debug + std::fmt::Display,
Self: core::fmt::Debug + core::fmt::Display,
#(#where_clauses),*
{
#description_fn
Expand Down Expand Up @@ -1606,12 +1606,12 @@ impl<'a> ErrorCompatImpl<'a> {
..
} = *backtrace_field;
quote! {
#enum_name::#variant_name { ref #field_name, .. } => { std::option::Option::Some(#field_name) }
#enum_name::#variant_name { ref #field_name, .. } => { core::option::Option::Some(#field_name) }
}
}
_ => {
quote! {
#enum_name::#variant_name { .. } => { std::option::Option::None }
#enum_name::#variant_name { .. } => { core::option::Option::None }
}
}
}
Expand Down Expand Up @@ -1673,19 +1673,19 @@ impl StructInfo {

let description_fn = quote! {
fn description(&self) -> &str {
std::error::Error::description(&self.0)
snafu::Error::description(&self.0)
}
};

let cause_fn = quote! {
fn cause(&self) -> Option<&dyn std::error::Error> {
std::error::Error::cause(&self.0)
fn cause(&self) -> Option<&dyn snafu::Error> {
snafu::Error::cause(&self.0)
}
};

let source_fn = quote! {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
std::error::Error::source(&self.0)
fn source(&self) -> Option<&(dyn snafu::Error + 'static)> {
snafu::Error::source(&self.0)
}
};

Expand All @@ -1700,7 +1700,7 @@ impl StructInfo {
};

let error_impl = quote! {
impl#generics std::error::Error for #parameterized_struct_name
impl#generics snafu::Error for #parameterized_struct_name
where
#(#where_clauses),*
{
Expand All @@ -1720,18 +1720,18 @@ impl StructInfo {
};

let display_impl = quote! {
impl#generics std::fmt::Display for #parameterized_struct_name
impl#generics core::fmt::Display for #parameterized_struct_name
where
#(#where_clauses),*
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::Display::fmt(&self.0, f)
}
}
};

let from_impl = quote! {
impl#generics std::convert::From<#inner_type> for #parameterized_struct_name
impl#generics core::convert::From<#inner_type> for #parameterized_struct_name
where
#(#where_clauses),*
{
Expand Down
20 changes: 10 additions & 10 deletions src/futures/try_future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
//!
//! [`TryFuture`]: futures_core::future::TryFuture

use crate::{ErrorCompat, IntoError};
use futures_core::future::TryFuture;
use pin_project::pin_project;
use std::{
use crate::{Error, ErrorCompat, IntoError};
use core::{
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context as TaskContext, Poll},
};
use futures_core::future::TryFuture;
use pin_project::pin_project;

/// Additions to [`TryFuture`].
pub trait TryFutureExt: TryFuture + Sized {
Expand Down Expand Up @@ -49,7 +49,7 @@ pub trait TryFutureExt: TryFuture + Sized {
fn context<C, E>(self, context: C) -> Context<Self, C, E>
where
C: IntoError<E, Source = Self::Error>,
E: std::error::Error + ErrorCompat;
E: Error + ErrorCompat;

/// Extend a [`TryFuture`]'s error with lazily-generated context-sensitive
/// information.
Expand Down Expand Up @@ -87,7 +87,7 @@ pub trait TryFutureExt: TryFuture + Sized {
where
F: FnOnce() -> C,
C: IntoError<E, Source = Self::Error>,
E: std::error::Error + ErrorCompat;
E: Error + ErrorCompat;
}

impl<Fut> TryFutureExt for Fut
Expand All @@ -97,7 +97,7 @@ where
fn context<C, E>(self, context: C) -> Context<Self, C, E>
where
C: IntoError<E, Source = Self::Error>,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
Context {
inner: self,
Expand All @@ -110,7 +110,7 @@ where
where
F: FnOnce() -> C,
C: IntoError<E, Source = Self::Error>,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
WithContext {
inner: self,
Expand All @@ -137,7 +137,7 @@ impl<Fut, C, E> Future for Context<Fut, C, E>
where
Fut: TryFuture,
C: IntoError<E, Source = Fut::Error>,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
type Output = Result<Fut::Ok, E>;

Expand Down Expand Up @@ -173,7 +173,7 @@ where
Fut: TryFuture,
F: FnOnce() -> C,
C: IntoError<E, Source = Fut::Error>,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
type Output = Result<Fut::Ok, E>;

Expand Down
20 changes: 10 additions & 10 deletions src/futures/try_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
//!
//! [`TryStream`]: futures_core::TryStream

use crate::{ErrorCompat, IntoError};
use futures_core::stream::{Stream, TryStream};
use pin_project::pin_project;
use std::{
use crate::{Error, ErrorCompat, IntoError};
use core::{
marker::PhantomData,
pin::Pin,
task::{Context as TaskContext, Poll},
};
use futures_core::stream::{Stream, TryStream};
use pin_project::pin_project;

/// Additions to [`TryStream`].
pub trait TryStreamExt: TryStream + Sized {
Expand Down Expand Up @@ -49,7 +49,7 @@ pub trait TryStreamExt: TryStream + Sized {
fn context<C, E>(self, context: C) -> Context<Self, C, E>
where
C: IntoError<E, Source = Self::Error> + Clone,
E: std::error::Error + ErrorCompat;
E: Error + ErrorCompat;

/// Extend a [`TryStream`]'s error with lazily-generated
/// context-sensitive information.
Expand Down Expand Up @@ -88,7 +88,7 @@ pub trait TryStreamExt: TryStream + Sized {
where
F: FnMut() -> C,
C: IntoError<E, Source = Self::Error>,
E: std::error::Error + ErrorCompat;
E: Error + ErrorCompat;
}

impl<St> TryStreamExt for St
Expand All @@ -98,7 +98,7 @@ where
fn context<C, E>(self, context: C) -> Context<Self, C, E>
where
C: IntoError<E, Source = Self::Error> + Clone,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
Context {
inner: self,
Expand All @@ -111,7 +111,7 @@ where
where
F: FnMut() -> C,
C: IntoError<E, Source = Self::Error>,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
WithContext {
inner: self,
Expand All @@ -138,7 +138,7 @@ impl<St, C, E> Stream for Context<St, C, E>
where
St: TryStream,
C: IntoError<E, Source = St::Error> + Clone,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
type Item = Result<St::Ok, E>;

Expand Down Expand Up @@ -177,7 +177,7 @@ where
St: TryStream,
F: FnMut() -> C,
C: IntoError<E, Source = St::Error>,
E: std::error::Error + ErrorCompat,
E: Error + ErrorCompat,
{
type Item = Result<St::Ok, E>;

Expand Down
Loading

0 comments on commit 7fbf5e3

Please sign in to comment.