-
-
Notifications
You must be signed in to change notification settings - Fork 183
core::error
, no_std
#304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core::error
, no_std
#304
Changes from all commits
6085f29
c560bcc
ec51e63
f7f6c77
f1d9df3
33b7a36
3663fd1
61b1c17
3e792e0
b278258
8cbdc4e
cc00ef8
7fa183b
28ce40b
0b058bc
e7e9341
bfd7357
706fb6a
a3d073b
89008c0
c9cd3b9
0ef9d1b
7182e3f
515bd36
2614b53
44737a5
e779e1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,8 @@ license = "MIT OR Apache-2.0" | |
repository = "https://github.com/dtolnay/thiserror" | ||
rust-version = "1.56" | ||
|
||
# without the `std` feature (i.e. `no_std`): rust-version = "1.81" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned in this comment, I feel we should attempt to widen our build compatibility to not break |
||
|
||
[dependencies] | ||
thiserror-impl = { version = "=1.0.64", path = "impl" } | ||
|
||
|
@@ -26,3 +28,11 @@ members = ["impl"] | |
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
rustdoc-args = ["--generate-link-to-definition"] | ||
|
||
[features] | ||
std = [] | ||
default = ["std"] | ||
|
||
[[test]] | ||
name = "test_path" | ||
required-features = ["std"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,7 @@ fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream { | |
|
||
#[allow(unused_qualifications)] | ||
#[automatically_derived] | ||
impl #impl_generics std::error::Error for #ty #ty_generics #where_clause | ||
impl #impl_generics ::thiserror::__private::error::Error for #ty #ty_generics #where_clause | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of interest, why did we choose this rather than hardcoding My slight concern is that use of |
||
where | ||
// Work around trivial bounds being unstable. | ||
// https://github.com/rust-lang/rust/issues/48214 | ||
|
@@ -62,17 +62,19 @@ fn impl_struct(input: Struct) -> TokenStream { | |
let source_body = if let Some(transparent_attr) = &input.attrs.transparent { | ||
let only_field = &input.fields[0]; | ||
if only_field.contains_generic { | ||
error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error)); | ||
error_inferred_bounds | ||
.insert(only_field.ty, quote!(::thiserror::__private::error::Error)); | ||
} | ||
let member = &only_field.member; | ||
Some(quote_spanned! {transparent_attr.span=> | ||
std::error::Error::source(self.#member.as_dyn_error()) | ||
::thiserror::__private::error::Error::source(self.#member.as_dyn_error()) | ||
}) | ||
} else if let Some(source_field) = input.source_field() { | ||
let source = &source_field.member; | ||
if source_field.contains_generic { | ||
let ty = unoptional_type(source_field.ty); | ||
error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static)); | ||
error_inferred_bounds | ||
.insert(ty, quote!(::thiserror::__private::error::Error + 'static)); | ||
} | ||
let asref = if type_is_option(source_field.ty) { | ||
Some(quote_spanned!(source.member_span()=> .as_ref()?)) | ||
|
@@ -90,8 +92,8 @@ fn impl_struct(input: Struct) -> TokenStream { | |
}; | ||
let source_method = source_body.map(|body| { | ||
quote! { | ||
fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> { | ||
use thiserror::__private::AsDynError as _; | ||
fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::__private::error::Error + 'static)> { | ||
use ::thiserror::__private::AsDynError as _; | ||
#body | ||
} | ||
} | ||
|
@@ -118,32 +120,32 @@ fn impl_struct(input: Struct) -> TokenStream { | |
} else if type_is_option(backtrace_field.ty) { | ||
Some(quote! { | ||
if let ::core::option::Option::Some(backtrace) = &self.#backtrace { | ||
#request.provide_ref::<std::backtrace::Backtrace>(backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(backtrace); | ||
} | ||
}) | ||
} else { | ||
Some(quote! { | ||
#request.provide_ref::<std::backtrace::Backtrace>(&self.#backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(&self.#backtrace); | ||
}) | ||
}; | ||
quote! { | ||
use thiserror::__private::ThiserrorProvide as _; | ||
use ::thiserror::__private::ThiserrorProvide as _; | ||
#source_provide | ||
#self_provide | ||
} | ||
} else if type_is_option(backtrace_field.ty) { | ||
quote! { | ||
if let ::core::option::Option::Some(backtrace) = &self.#backtrace { | ||
#request.provide_ref::<std::backtrace::Backtrace>(backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(backtrace); | ||
} | ||
} | ||
} else { | ||
quote! { | ||
#request.provide_ref::<std::backtrace::Backtrace>(&self.#backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(&self.#backtrace); | ||
} | ||
}; | ||
quote! { | ||
fn provide<'_request>(&'_request self, #request: &mut std::error::Request<'_request>) { | ||
fn provide<'_request>(&'_request self, #request: &mut ::thiserror::__private::error::Request<'_request>) { | ||
#body | ||
} | ||
} | ||
|
@@ -216,7 +218,7 @@ fn impl_struct(input: Struct) -> TokenStream { | |
quote! { | ||
#[allow(unused_qualifications)] | ||
#[automatically_derived] | ||
impl #impl_generics std::error::Error for #ty #ty_generics #error_where_clause { | ||
impl #impl_generics ::thiserror::__private::error::Error for #ty #ty_generics #error_where_clause { | ||
#source_method | ||
#provide_method | ||
} | ||
|
@@ -236,11 +238,11 @@ fn impl_enum(input: Enum) -> TokenStream { | |
if let Some(transparent_attr) = &variant.attrs.transparent { | ||
let only_field = &variant.fields[0]; | ||
if only_field.contains_generic { | ||
error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error)); | ||
error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::__private::error::Error)); | ||
} | ||
let member = &only_field.member; | ||
let source = quote_spanned! {transparent_attr.span=> | ||
std::error::Error::source(transparent.as_dyn_error()) | ||
::thiserror::__private::error::Error::source(transparent.as_dyn_error()) | ||
}; | ||
quote! { | ||
#ty::#ident {#member: transparent} => #source, | ||
|
@@ -249,7 +251,7 @@ fn impl_enum(input: Enum) -> TokenStream { | |
let source = &source_field.member; | ||
if source_field.contains_generic { | ||
let ty = unoptional_type(source_field.ty); | ||
error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static)); | ||
error_inferred_bounds.insert(ty, quote!(::thiserror::__private::error::Error + 'static)); | ||
} | ||
let asref = if type_is_option(source_field.ty) { | ||
Some(quote_spanned!(source.member_span()=> .as_ref()?)) | ||
|
@@ -270,8 +272,8 @@ fn impl_enum(input: Enum) -> TokenStream { | |
} | ||
}); | ||
Some(quote! { | ||
fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> { | ||
use thiserror::__private::AsDynError as _; | ||
fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::__private::error::Error + 'static)> { | ||
use ::thiserror::__private::AsDynError as _; | ||
#[allow(deprecated)] | ||
match self { | ||
#(#arms)* | ||
|
@@ -307,12 +309,12 @@ fn impl_enum(input: Enum) -> TokenStream { | |
let self_provide = if type_is_option(backtrace_field.ty) { | ||
quote! { | ||
if let ::core::option::Option::Some(backtrace) = backtrace { | ||
#request.provide_ref::<std::backtrace::Backtrace>(backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(backtrace); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MINOR: It may be nice if we gave a better compiler error if a user tried to specify a backtrace when we're not in ... that said, it might actually cause more breakage if people are using So maybe safer to leave this as-is, and perhaps document that this only works if compiling with |
||
} | ||
} | ||
} else { | ||
quote! { | ||
#request.provide_ref::<std::backtrace::Backtrace>(backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(backtrace); | ||
} | ||
}; | ||
quote! { | ||
|
@@ -321,7 +323,7 @@ fn impl_enum(input: Enum) -> TokenStream { | |
#source: #varsource, | ||
.. | ||
} => { | ||
use thiserror::__private::ThiserrorProvide as _; | ||
use ::thiserror::__private::ThiserrorProvide as _; | ||
#source_provide | ||
#self_provide | ||
} | ||
|
@@ -345,7 +347,7 @@ fn impl_enum(input: Enum) -> TokenStream { | |
}; | ||
quote! { | ||
#ty::#ident {#backtrace: #varsource, ..} => { | ||
use thiserror::__private::ThiserrorProvide as _; | ||
use ::thiserror::__private::ThiserrorProvide as _; | ||
#source_provide | ||
} | ||
} | ||
|
@@ -355,12 +357,12 @@ fn impl_enum(input: Enum) -> TokenStream { | |
let body = if type_is_option(backtrace_field.ty) { | ||
quote! { | ||
if let ::core::option::Option::Some(backtrace) = backtrace { | ||
#request.provide_ref::<std::backtrace::Backtrace>(backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(backtrace); | ||
} | ||
} | ||
} else { | ||
quote! { | ||
#request.provide_ref::<std::backtrace::Backtrace>(backtrace); | ||
#request.provide_ref::<::std::backtrace::Backtrace>(backtrace); | ||
} | ||
}; | ||
quote! { | ||
|
@@ -375,7 +377,7 @@ fn impl_enum(input: Enum) -> TokenStream { | |
} | ||
}); | ||
Some(quote! { | ||
fn provide<'_request>(&'_request self, #request: &mut std::error::Request<'_request>) { | ||
fn provide<'_request>(&'_request self, #request: &mut ::thiserror::__private::error::Request<'_request>) { | ||
#[allow(deprecated)] | ||
match self { | ||
#(#arms)* | ||
|
@@ -475,7 +477,7 @@ fn impl_enum(input: Enum) -> TokenStream { | |
quote! { | ||
#[allow(unused_qualifications)] | ||
#[automatically_derived] | ||
impl #impl_generics std::error::Error for #ty #ty_generics #error_where_clause { | ||
impl #impl_generics ::thiserror::__private::error::Error for #ty #ty_generics #error_where_clause { | ||
#source_method | ||
#provide_method | ||
} | ||
|
@@ -502,7 +504,7 @@ fn fields_pat(fields: &[Field]) -> TokenStream { | |
fn use_as_display(needs_as_display: bool) -> Option<TokenStream> { | ||
if needs_as_display { | ||
Some(quote! { | ||
use thiserror::__private::AsDisplay as _; | ||
use ::thiserror::__private::AsDisplay as _; | ||
}) | ||
} else { | ||
None | ||
|
@@ -520,11 +522,11 @@ fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> Toke | |
let backtrace_member = &backtrace_field.member; | ||
if type_is_option(backtrace_field.ty) { | ||
quote! { | ||
#backtrace_member: ::core::option::Option::Some(std::backtrace::Backtrace::capture()), | ||
#backtrace_member: ::core::option::Option::Some(::std::backtrace::Backtrace::capture()), | ||
} | ||
} else { | ||
quote! { | ||
#backtrace_member: ::core::convert::From::from(std::backtrace::Backtrace::capture()), | ||
#backtrace_member: ::core::convert::From::from(::std::backtrace::Backtrace::capture()), | ||
} | ||
} | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#![no_std] | ||
use thiserror::Error; | ||
|
||
#[derive(Error, Debug)] | ||
#[error("io")] | ||
pub struct IoError; | ||
|
||
#[derive(Error, Debug)] | ||
pub enum MyError { | ||
#[error("A")] | ||
A, | ||
#[error("B {0}")] | ||
B(#[from] IoError), | ||
} | ||
|
||
#[test] | ||
#[cfg(not(feature = "std"))] | ||
fn test_no_std() { | ||
use core::error::Error as _; | ||
|
||
let error = MyError::from(IoError); | ||
error.source().unwrap().downcast_ref::<IoError>().unwrap(); | ||
} |
Uh oh!
There was an error while loading. Please reload this page.