allow implementing `core::error::Error` when available
rust 1.81.0 made std::error::Error available in core.
Users with that version or higher should be getting the Error impl no matter if std feature is enabled.
fixes #179 without introducing a breaking change
I think its good
lib.rs
use nutype::nutype;
#[nutype(validate(finite))]
struct A(f32);
Cargo.toml
[dependencies]
nutype = { path = "../nutype/nutype" }
Outputs of cargo expand
1.81.0
=> impl ::core::error::Error for AError { /* ... */ }
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use nutype::nutype;
#[doc(hidden)]
mod __nutype_A__ {
use super::*;
pub struct A(f32);
#[allow(clippy::enum_variant_names)]
pub enum AError {
FiniteViolated,
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::fmt::Debug for AError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FiniteViolated")
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::clone::Clone for AError {
#[inline]
fn clone(&self) -> AError {
AError::FiniteViolated
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::marker::StructuralPartialEq for AError {}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::PartialEq for AError {
#[inline]
fn eq(&self, other: &AError) -> bool {
true
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::Eq for AError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
impl ::core::fmt::Display for AError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
AError::FiniteViolated => {
f.write_fmt(format_args!("{0} is not finite.", "A"))
}
}
}
}
impl ::core::error::Error for AError {
fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
None
}
}
impl A {
pub fn try_new(raw_value: f32) -> ::core::result::Result<Self, AError> {
let sanitized_value: f32 = Self::__sanitize__(raw_value);
Self::__validate__(&sanitized_value)?;
Ok(A(sanitized_value))
}
fn __sanitize__(mut value: f32) -> f32 {
value
}
fn __validate__(val: &f32) -> core::result::Result<(), AError> {
let val = *val;
if !val.is_finite() {
return Err(AError::FiniteViolated);
}
Ok(())
}
#[deprecated(since = "0.4.3", note = "\nUse `try_new` instead.")]
pub fn new(raw_value: f32) -> ::core::result::Result<Self, AError> {
Self::try_new(raw_value)
}
}
impl A {
#[inline]
pub fn into_inner(self) -> f32 {
self.0
}
}
}
use __nutype_A__::A;
use __nutype_A__::AError;
=> impl ::core::error::Error for AError { /* ... */ }
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use nutype::nutype;
#[doc(hidden)]
mod __nutype_A__ {
use super::*;
pub struct A(f32);
#[allow(clippy::enum_variant_names)]
pub enum AError {
FiniteViolated,
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::fmt::Debug for AError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FiniteViolated")
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::clone::Clone for AError {
#[inline]
fn clone(&self) -> AError {
AError::FiniteViolated
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::marker::StructuralPartialEq for AError {}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::PartialEq for AError {
#[inline]
fn eq(&self, other: &AError) -> bool {
true
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::Eq for AError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
impl ::core::fmt::Display for AError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
AError::FiniteViolated => {
f.write_fmt(format_args!("{0} is not finite.", "A"))
}
}
}
}
impl ::core::error::Error for AError {
fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
None
}
}
impl A {
pub fn try_new(raw_value: f32) -> ::core::result::Result<Self, AError> {
let sanitized_value: f32 = Self::__sanitize__(raw_value);
Self::__validate__(&sanitized_value)?;
Ok(A(sanitized_value))
}
fn __sanitize__(mut value: f32) -> f32 {
value
}
fn __validate__(val: &f32) -> core::result::Result<(), AError> {
let val = *val;
if !val.is_finite() {
return Err(AError::FiniteViolated);
}
Ok(())
}
#[deprecated(since = "0.4.3", note = "\nUse `try_new` instead.")]
pub fn new(raw_value: f32) -> ::core::result::Result<Self, AError> {
Self::try_new(raw_value)
}
}
impl A {
#[inline]
pub fn into_inner(self) -> f32 {
self.0
}
}
}
use __nutype_A__::A;
use __nutype_A__::AError;
1.80.0
=> impl ::std::error::Error for AError { /* ... */ }
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use nutype::nutype;
#[doc(hidden)]
mod __nutype_A__ {
use super::*;
pub struct A(f32);
#[allow(clippy::enum_variant_names)]
pub enum AError {
FiniteViolated,
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::fmt::Debug for AError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FiniteViolated")
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::clone::Clone for AError {
#[inline]
fn clone(&self) -> AError {
AError::FiniteViolated
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::marker::StructuralPartialEq for AError {}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::PartialEq for AError {
#[inline]
fn eq(&self, other: &AError) -> bool {
true
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::Eq for AError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
impl ::core::fmt::Display for AError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
AError::FiniteViolated => {
f.write_fmt(format_args!("{0} is not finite.", "A"))
}
}
}
}
impl ::std::error::Error for AError {
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
None
}
}
impl A {
pub fn try_new(raw_value: f32) -> ::core::result::Result<Self, AError> {
let sanitized_value: f32 = Self::__sanitize__(raw_value);
Self::__validate__(&sanitized_value)?;
Ok(A(sanitized_value))
}
fn __sanitize__(mut value: f32) -> f32 {
value
}
fn __validate__(val: &f32) -> core::result::Result<(), AError> {
let val = *val;
if !val.is_finite() {
return Err(AError::FiniteViolated);
}
Ok(())
}
#[deprecated(since = "0.4.3", note = "\nUse `try_new` instead.")]
pub fn new(raw_value: f32) -> ::core::result::Result<Self, AError> {
Self::try_new(raw_value)
}
}
impl A {
#[inline]
pub fn into_inner(self) -> f32 {
self.0
}
}
}
use __nutype_A__::A;
use __nutype_A__::AError;
=> No implementation of Error
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use nutype::nutype;
#[doc(hidden)]
mod __nutype_A__ {
use super::*;
pub struct A(f32);
#[allow(clippy::enum_variant_names)]
pub enum AError {
FiniteViolated,
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::fmt::Debug for AError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FiniteViolated")
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::clone::Clone for AError {
#[inline]
fn clone(&self) -> AError {
AError::FiniteViolated
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::marker::StructuralPartialEq for AError {}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::PartialEq for AError {
#[inline]
fn eq(&self, other: &AError) -> bool {
true
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::Eq for AError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
impl ::core::fmt::Display for AError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
AError::FiniteViolated => {
f.write_fmt(format_args!("{0} is not finite.", "A"))
}
}
}
}
impl A {
pub fn try_new(raw_value: f32) -> ::core::result::Result<Self, AError> {
let sanitized_value: f32 = Self::__sanitize__(raw_value);
Self::__validate__(&sanitized_value)?;
Ok(A(sanitized_value))
}
fn __sanitize__(mut value: f32) -> f32 {
value
}
fn __validate__(val: &f32) -> core::result::Result<(), AError> {
let val = *val;
if !val.is_finite() {
return Err(AError::FiniteViolated);
}
Ok(())
}
#[deprecated(since = "0.4.3", note = "\nUse `try_new` instead.")]
pub fn new(raw_value: f32) -> ::core::result::Result<Self, AError> {
Self::try_new(raw_value)
}
}
impl A {
#[inline]
pub fn into_inner(self) -> f32 {
self.0
}
}
}
use __nutype_A__::A;
use __nutype_A__::AError;
1.83.0-nightly
=> impl ::std::error::Error for AError { /* ... */ }
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use nutype::nutype;
#[doc(hidden)]
mod __nutype_A__ {
use super::*;
pub struct A(f32);
#[allow(clippy::enum_variant_names)]
pub enum AError {
FiniteViolated,
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::fmt::Debug for AError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FiniteViolated")
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::clone::Clone for AError {
#[inline]
fn clone(&self) -> AError {
AError::FiniteViolated
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::marker::StructuralPartialEq for AError {}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::PartialEq for AError {
#[inline]
fn eq(&self, other: &AError) -> bool {
true
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::Eq for AError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
impl ::core::fmt::Display for AError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
AError::FiniteViolated => {
f.write_fmt(format_args!("{0} is not finite.", "A"))
}
}
}
}
impl ::core::error::Error for AError {
fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
None
}
}
impl A {
pub fn try_new(raw_value: f32) -> ::core::result::Result<Self, AError> {
let sanitized_value: f32 = Self::__sanitize__(raw_value);
Self::__validate__(&sanitized_value)?;
Ok(A(sanitized_value))
}
fn __sanitize__(mut value: f32) -> f32 {
value
}
fn __validate__(val: &f32) -> core::result::Result<(), AError> {
let val = *val;
if !val.is_finite() {
return Err(AError::FiniteViolated);
}
Ok(())
}
#[deprecated(since = "0.4.3", note = "\nUse `try_new` instead.")]
pub fn new(raw_value: f32) -> ::core::result::Result<Self, AError> {
Self::try_new(raw_value)
}
}
impl A {
#[inline]
pub fn into_inner(self) -> f32 {
self.0
}
}
}
use __nutype_A__::A;
use __nutype_A__::AError;
=> impl ::core::error::Error for AError { /* ... */ }
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use nutype::nutype;
#[doc(hidden)]
mod __nutype_A__ {
use super::*;
pub struct A(f32);
#[allow(clippy::enum_variant_names)]
pub enum AError {
FiniteViolated,
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::fmt::Debug for AError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FiniteViolated")
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::clone::Clone for AError {
#[inline]
fn clone(&self) -> AError {
AError::FiniteViolated
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::marker::StructuralPartialEq for AError {}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::PartialEq for AError {
#[inline]
fn eq(&self, other: &AError) -> bool {
true
}
}
#[automatically_derived]
#[allow(clippy::enum_variant_names)]
impl ::core::cmp::Eq for AError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
impl ::core::fmt::Display for AError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
AError::FiniteViolated => {
f.write_fmt(format_args!("{0} is not finite.", "A"))
}
}
}
}
impl ::core::error::Error for AError {
fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
None
}
}
impl A {
pub fn try_new(raw_value: f32) -> ::core::result::Result<Self, AError> {
let sanitized_value: f32 = Self::__sanitize__(raw_value);
Self::__validate__(&sanitized_value)?;
Ok(A(sanitized_value))
}
fn __sanitize__(mut value: f32) -> f32 {
value
}
fn __validate__(val: &f32) -> core::result::Result<(), AError> {
let val = *val;
if !val.is_finite() {
return Err(AError::FiniteViolated);
}
Ok(())
}
#[deprecated(since = "0.4.3", note = "\nUse `try_new` instead.")]
pub fn new(raw_value: f32) -> ::core::result::Result<Self, AError> {
Self::try_new(raw_value)
}
}
impl A {
#[inline]
pub fn into_inner(self) -> f32 {
self.0
}
}
}
use __nutype_A__::A;
use __nutype_A__::AError;
@vic1707 Hi thanks for your PRs. Just to keep you update: sorry for the delay. I had seen them and wanted to review over the weekend by did not manage to. I'll try to process them on the next weekend.
No problem take your time π Thanks for telling me
Added the cargo expand on nightly just to be sure I didn't ruin everything.
Hi @greyblake may I ask for an update ?
Hi, sorry I am on vacation, will be back in 10 days.
On Sun, Sep 29, 2024, 18:21 Victor LEFEBVRE @.***> wrote:
Hi @greyblake https://github.com/greyblake may I ask for an update ?
β Reply to this email directly, view it on GitHub https://github.com/greyblake/nutype/pull/184#issuecomment-2381396546, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA3W2E7SJ4AGSQFV5CHHQTZZALGPAVCNFSM6AAAAABOE6I4NSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGOBRGM4TMNJUGY . You are receiving this because you were mentioned.Message ID: @.***>
Hi @greyblake may I ask for an update ?
@vic1707 Sorry, I'll try to merge this on the weekend.
@vic1707 Thank you for your contribution and again sorry for the delay. I've dropped 2 tiny comments. Let me know if you'd like to address them, if no, I guess I can do it.
@greyblake, just pushed a dryer version, what do you think ?
I thought of doing
let error = cfg_if! {
if #[cfg(ERROR_IN_CORE)] {
quote! { ::core::error::Error }
} else {
quote! { ::std::error::Error }
}
};
instead of the proposed version but it's not yet supported by rust itself, see: https://github.com/rust-lang/rust/issues/15701.
Also, do you think you could publish a new version after this merge ?
@vic1707 Sorry by bad, in my thinking I assumed that we could just use the core:: variant. With a fresh head, I see that it's obviously would be contra-productive and could not work with the older rust versions.
Thank you very much for the very hard try to DRY it.
No problem, it helped me get a dryer version out, win-win π. How about releasing 0.5.1 @greyblake ? Since 0.5.0 we got a few fixes and QOL improvements π