From 2eb399b27ab92f3e558618d2a9115b7f0cc8e3bf Mon Sep 17 00:00:00 2001 From: IcyDefiance Date: Thu, 20 Feb 2020 20:36:52 -0500 Subject: [PATCH 1/2] Support no_std --- Cargo.toml | 6 +++++- impl/Cargo.toml | 4 ++++ impl/src/expand.rs | 42 +++++++++++++++++++++++++++++++++++------- impl/src/prop.rs | 9 ++++++++- src/display.rs | 4 ++++ src/lib.rs | 19 ++++++++++++++++++- 6 files changed, 74 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ecae718..f74faf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" travis-ci = { repository = "dtolnay/thiserror" } [dependencies] -thiserror-impl = { version = "=1.0.11", path = "impl" } +thiserror-impl = { version = "=1.0.11", path = "impl", default-features = false } [dev-dependencies] anyhow = "1.0" @@ -22,5 +22,9 @@ ref-cast = "1.0" rustversion = "1.0" trybuild = { version = "1.0.19", features = ["diff"] } +[features] +default = ["std"] +std = ["thiserror-impl/std"] + [workspace] members = ["impl"] diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 931b3fd..cceaff0 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -17,3 +17,7 @@ travis-ci = { repository = "dtolnay/thiserror" } proc-macro2 = "1.0" quote = "1.0" syn = "1.0.11" + +[features] +default = ["std"] +std = [] diff --git a/impl/src/expand.rs b/impl/src/expand.rs index 51b9c9e..94aeeed 100644 --- a/impl/src/expand.rs +++ b/impl/src/expand.rs @@ -1,6 +1,9 @@ use crate::ast::{Enum, Field, Input, Struct}; use proc_macro2::TokenStream; -use quote::{format_ident, quote, quote_spanned, ToTokens}; +#[cfg(feature = "std")] +use quote::quote_spanned; +use quote::{format_ident, quote, ToTokens}; +#[cfg(feature = "std")] use syn::spanned::Spanned; use syn::{DeriveInput, Member, PathArguments, Result, Type}; @@ -17,6 +20,7 @@ fn impl_struct(input: Struct) -> TokenStream { let ty = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + #[cfg(feature = "std")] let source_body = if input.attrs.transparent.is_some() { let only_field = &input.fields[0].member; Some(quote! { @@ -36,6 +40,7 @@ fn impl_struct(input: Struct) -> TokenStream { } else { None }; + #[cfg(feature = "std")] let source_method = source_body.map(|body| { quote! { fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> { @@ -45,6 +50,7 @@ fn impl_struct(input: Struct) -> TokenStream { } }); + #[cfg(feature = "std")] let backtrace_method = input.backtrace_field().map(|backtrace_field| { let backtrace = &backtrace_field.member; let body = if let Some(source_field) = input.source_field() { @@ -96,7 +102,10 @@ fn impl_struct(input: Struct) -> TokenStream { let use_as_display = if display.has_bonus_display { Some(quote! { #[allow(unused_imports)] - use thiserror::private::{DisplayAsDisplay, PathAsDisplay}; + use thiserror::private::DisplayAsDisplay; + #[cfg(feature = "std")] + #[allow(unused_imports)] + use thiserror::private::PathAsDisplay; }) } else { None @@ -126,7 +135,7 @@ fn impl_struct(input: Struct) -> TokenStream { let from = from_field.ty; let body = from_initializer(from_field, backtrace_field); quote! { - impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause { + impl #impl_generics core::convert::From<#from> for #ty #ty_generics #where_clause { fn from(source: #from) -> Self { #ty #body } @@ -134,11 +143,18 @@ fn impl_struct(input: Struct) -> TokenStream { } }); - quote! { + #[cfg(feature = "std")] + let error_impl = quote! { impl #impl_generics std::error::Error for #ty #ty_generics #where_clause { #source_method #backtrace_method } + }; + #[cfg(not(feature = "std"))] + let error_impl = quote! {}; + + quote! { + #error_impl #display_impl #from_impl } @@ -148,6 +164,7 @@ fn impl_enum(input: Enum) -> TokenStream { let ty = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + #[cfg(feature = "std")] let source_method = if input.has_source() { let arms = input.variants.iter().map(|variant| { let ident = &variant.ident; @@ -186,6 +203,7 @@ fn impl_enum(input: Enum) -> TokenStream { None }; + #[cfg(feature = "std")] let backtrace_method = if input.has_backtrace() { let arms = input.variants.iter().map(|variant| { let ident = &variant.ident; @@ -260,7 +278,10 @@ fn impl_enum(input: Enum) -> TokenStream { }) { Some(quote! { #[allow(unused_imports)] - use thiserror::private::{DisplayAsDisplay, PathAsDisplay}; + use thiserror::private::DisplayAsDisplay; + #[allow(unused_imports)] + #[cfg(feature = "std")] + use thiserror::private::PathAsDisplay; }) } else { None @@ -309,7 +330,7 @@ fn impl_enum(input: Enum) -> TokenStream { let from = from_field.ty; let body = from_initializer(from_field, backtrace_field); Some(quote! { - impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause { + impl #impl_generics core::convert::From<#from> for #ty #ty_generics #where_clause { fn from(source: #from) -> Self { #ty::#variant #body } @@ -317,11 +338,18 @@ fn impl_enum(input: Enum) -> TokenStream { }) }); - quote! { + #[cfg(feature = "std")] + let error_impl = quote! { impl #impl_generics std::error::Error for #ty #ty_generics #where_clause { #source_method #backtrace_method } + }; + #[cfg(not(feature = "std"))] + let error_impl = quote! {}; + + quote! { + #error_impl #display_impl #(#from_impls)* } diff --git a/impl/src/prop.rs b/impl/src/prop.rs index e011848..4d780fe 100644 --- a/impl/src/prop.rs +++ b/impl/src/prop.rs @@ -1,11 +1,14 @@ use crate::ast::{Enum, Field, Struct, Variant}; -use syn::{Member, Type}; +#[cfg(feature = "std")] +use syn::Member; +use syn::Type; impl Struct<'_> { pub(crate) fn from_field(&self) -> Option<&Field> { from_field(&self.fields) } + #[cfg(feature = "std")] pub(crate) fn source_field(&self) -> Option<&Field> { source_field(&self.fields) } @@ -16,12 +19,14 @@ impl Struct<'_> { } impl Enum<'_> { + #[cfg(feature = "std")] pub(crate) fn has_source(&self) -> bool { self.variants .iter() .any(|variant| variant.source_field().is_some() || variant.attrs.transparent.is_some()) } + #[cfg(feature = "std")] pub(crate) fn has_backtrace(&self) -> bool { self.variants .iter() @@ -47,6 +52,7 @@ impl Variant<'_> { from_field(&self.fields) } + #[cfg(feature = "std")] pub(crate) fn source_field(&self) -> Option<&Field> { source_field(&self.fields) } @@ -71,6 +77,7 @@ fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { None } +#[cfg(feature = "std")] fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { for field in fields { if field.attrs.from.is_some() || field.attrs.source.is_some() { diff --git a/src/display.rs b/src/display.rs index 0eb0dd9..355010c 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,4 +1,5 @@ use std::fmt::Display; +#[cfg(feature = "std")] use std::path::{self, Path, PathBuf}; pub trait DisplayAsDisplay { @@ -11,16 +12,19 @@ impl DisplayAsDisplay for &T { } } +#[cfg(feature = "std")] pub trait PathAsDisplay { fn as_display(&self) -> path::Display<'_>; } +#[cfg(feature = "std")] impl PathAsDisplay for Path { fn as_display(&self) -> path::Display<'_> { self.display() } } +#[cfg(feature = "std")] impl PathAsDisplay for PathBuf { fn as_display(&self) -> path::Display<'_> { self.display() diff --git a/src/lib.rs b/src/lib.rs index 4a60a52..65af369 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,6 +176,20 @@ //! //! [`anyhow`]: https://github.com/dtolnay/anyhow +// always enabled to force devs to add imports for things like Vec and String, even when working +// with std +#![no_std] + +#[cfg(not(feature = "std"))] +#[allow(unused_imports)] +#[macro_use] +extern crate alloc as std; +#[cfg(feature = "std")] +#[allow(unused_imports)] +#[macro_use] +extern crate std; + +#[cfg(feature = "std")] mod aserror; mod display; @@ -184,6 +198,9 @@ pub use thiserror_impl::*; // Not public API. #[doc(hidden)] pub mod private { + #[cfg(feature = "std")] pub use crate::aserror::AsDynError; - pub use crate::display::{DisplayAsDisplay, PathAsDisplay}; + pub use crate::display::DisplayAsDisplay; + #[cfg(feature = "std")] + pub use crate::display::PathAsDisplay; } From 3c67f09db91c687006555eaf8c30695c9264016a Mon Sep 17 00:00:00 2001 From: IcyDefiance Date: Fri, 21 Feb 2020 19:43:33 -0500 Subject: [PATCH 2/2] Improve comment --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 65af369..6f11dd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,8 +176,8 @@ //! //! [`anyhow`]: https://github.com/dtolnay/anyhow -// always enabled to force devs to add imports for things like Vec and String, even when working -// with std +// Always enabled to force devs to add use statements for things like Vec and String, even when +// working with std. #![no_std] #[cfg(not(feature = "std"))]