Skip to content

Commit

Permalink
Merge pull request #184 from vic1707/error-in-core
Browse files Browse the repository at this point in the history
allow implementing `core::error::Error` when available
  • Loading branch information
greyblake authored Nov 9, 2024
2 parents 265c0dd + d8239e8 commit d398ce8
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 13 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions nutype_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ cfg-if = "1.0"
kinded = "0.3.0"
urlencoding = "2.0"

[build-dependencies]
rustc_version = "0.4.1"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(ERROR_IN_CORE)'] }

[lib]
proc-macro = true

Expand Down
20 changes: 20 additions & 0 deletions nutype_macros/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use rustc_version::{version, version_meta, Channel};

fn main() {
let version = version().expect("Couldn't get Rust version");
let version_meta = version_meta().expect("Couldn't get Rust channel");

// Assert we haven't travelled back in time
assert!(
version.major >= 1,
"How did you get a version before 1.0.0?"
);

// Generic setting
println!("cargo:rerun-if-changed=build.rs");

// feature `error-in-core` landed in rust 1.81.0
if matches!(version_meta.channel, Channel::Nightly) || version.minor >= 81 {
println!("cargo:rustc-cfg=ERROR_IN_CORE");
}
}
17 changes: 12 additions & 5 deletions nutype_macros/src/common/gen/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,22 @@ pub fn gen_error_type_name(type_name: &TypeName) -> ErrorTypePath {
ErrorTypePath::new(ident)
}

// NOTE: There is no `::core::error::Error` yet in stable Rust.
// So for `no_std` we just don't implement `Error` trait.
// NOTE: `::core::error::Error` is stable only for rust >= 1.81.0.
#[allow(unused_variables)]
pub fn gen_impl_error_trait(error_type_path: &ErrorTypePath) -> TokenStream {
cfg_if! {
if #[cfg(feature = "std")] {
if #[cfg(any(ERROR_IN_CORE, feature = "std"))] {
cfg_if! {
if #[cfg(ERROR_IN_CORE)] {
let error = quote! { ::core::error::Error };
} else {
let error = quote! { ::std::error::Error };
}
};

quote! {
impl ::std::error::Error for #error_type_path {
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
impl #error for #error_type_path {
fn source(&self) -> Option<&(dyn #error + 'static)> {
None
}
}
Expand Down
22 changes: 14 additions & 8 deletions nutype_macros/src/common/gen/parse_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,33 @@ pub fn gen_def_parse_error(
};

cfg_if! {
if #[cfg(feature = "std")] {
if #[cfg(any(ERROR_IN_CORE, feature = "std"))] {
cfg_if! {
if #[cfg(ERROR_IN_CORE)] {
let error = quote! { ::core::error::Error };
} else {
let error = quote! { ::std::error::Error };
}
};
let generics_with_fromstr_and_debug_bounds = add_bound_to_all_type_params(
&generics_with_fromstr_bound,
syn::parse_quote!(::core::fmt::Debug),
);
let impl_std_error = quote! {
impl #generics_with_fromstr_and_debug_bounds ::std::error::Error for #parse_error_type_name #generics_without_bounds {
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
let impl_error = quote! {
impl #generics_with_fromstr_and_debug_bounds #error for #parse_error_type_name #generics_without_bounds {
fn source(&self) -> Option<&(dyn #error + 'static)> {
None
}
}
};
} else {
// NOTE: There is no `::core::error::Error` yet in stable Rust.
// So for `no_std` we just don't implement `Error` trait.
let impl_std_error = quote! {};
// NOTE: `::core::error::Error` is stable only for rust >= 1.81.0.
let impl_error = quote! {};
}
};

quote! {
#definition
#impl_std_error
#impl_error
}
}

0 comments on commit d398ce8

Please sign in to comment.