From 155645a1b04e0475daba7c1c433815e302f93d0f Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Fri, 31 May 2024 21:53:04 +0200 Subject: [PATCH 01/12] Support for generic types --- dummy/src/main.rs | 7 ++-- nutype_macros/src/any/gen/mod.rs | 4 +- nutype_macros/src/common/gen/mod.rs | 58 +++++++++++++++----------- nutype_macros/src/common/models.rs | 8 ++++ nutype_macros/src/common/parse/meta.rs | 3 +- nutype_macros/src/float/gen/mod.rs | 4 +- nutype_macros/src/integer/gen/mod.rs | 4 +- nutype_macros/src/string/gen/mod.rs | 4 +- 8 files changed, 55 insertions(+), 37 deletions(-) diff --git a/dummy/src/main.rs b/dummy/src/main.rs index 36bfb66..606991c 100644 --- a/dummy/src/main.rs +++ b/dummy/src/main.rs @@ -1,10 +1,9 @@ use nutype::nutype; #[nutype( - validate(predicate = |v| v), - derive(Default), - default = true + sanitize(with = |v| v), + validate(predicate = |v| v.len() > 0) )] -pub struct TestData(bool); +struct NonEmptyVec(Vec); fn main() {} diff --git a/nutype_macros/src/any/gen/mod.rs b/nutype_macros/src/any/gen/mod.rs index 9eead88..6feacec 100644 --- a/nutype_macros/src/any/gen/mod.rs +++ b/nutype_macros/src/any/gen/mod.rs @@ -53,7 +53,7 @@ impl GenerateNewtype for AnyNewtype { .collect(); quote!( - fn sanitize(mut value: #inner_type) -> #inner_type { + fn __sanitize__(mut value: #inner_type) -> #inner_type { #transformations value } @@ -88,7 +88,7 @@ impl GenerateNewtype for AnyNewtype { .collect(); quote!( - fn validate<'a>(val: &'a #inner_type) -> ::core::result::Result<(), #error_name> { + fn __validate__<'a>(val: &'a #inner_type) -> ::core::result::Result<(), #error_name> { #validations Ok(()) } diff --git a/nutype_macros/src/common/gen/mod.rs b/nutype_macros/src/common/gen/mod.rs index ee17f09..7232533 100644 --- a/nutype_macros/src/common/gen/mod.rs +++ b/nutype_macros/src/common/gen/mod.rs @@ -20,7 +20,7 @@ use crate::common::{ }; use proc_macro2::{Punct, Spacing, TokenStream, TokenTree}; use quote::{format_ident, quote, ToTokens}; -use syn::Visibility; +use syn::{Generics, Visibility}; /// Inject an inner type into a closure, so compiler does not complain if the token stream matchers /// the expected closure pattern. @@ -133,9 +133,13 @@ pub fn gen_reimports( } } -pub fn gen_impl_into_inner(type_name: &TypeName, inner_type: impl ToTokens) -> TokenStream { +pub fn gen_impl_into_inner( + type_name: &TypeName, + generics: &Generics, + inner_type: impl ToTokens, +) -> TokenStream { quote! { - impl #type_name { + impl #generics #type_name #generics { #[inline] pub fn into_inner(self) -> #inner_type { self.0 @@ -187,14 +191,15 @@ pub trait GenerateNewtype { fn gen_new_with_validation( type_name: &TypeName, + generics: &Generics, inner_type: &Self::InnerType, sanitizers: &[Self::Sanitizer], validators: &[Self::Validator], ) -> TokenStream { - let sanitize = Self::gen_fn_sanitize(inner_type, sanitizers); + let fn_sanitize = Self::gen_fn_sanitize(inner_type, sanitizers); let validation_error = Self::gen_validation_error_type(type_name, validators); let error_type_name = gen_error_type_name(type_name); - let validate = Self::gen_fn_validate(inner_type, type_name, validators); + let fn_validate = Self::gen_fn_validate(inner_type, type_name, validators); let (input_type, convert_raw_value_if_necessary) = if Self::NEW_CONVERT_INTO_INNER_TYPE { ( @@ -208,29 +213,30 @@ pub trait GenerateNewtype { quote!( #validation_error - impl #type_name { + impl #generics #type_name #generics { pub fn new(raw_value: #input_type) -> ::core::result::Result { - // Keep sanitize() and validate() within new() so they do not overlap with outer - // scope imported with `use super::*`. - #sanitize - #validate - #convert_raw_value_if_necessary - let sanitized_value: #inner_type = sanitize(raw_value); - validate(&sanitized_value)?; + let sanitized_value: #inner_type = Self::__sanitize__(raw_value); + Self::__validate__(&sanitized_value)?; Ok(#type_name(sanitized_value)) } + + // Definite associated private functions __sanitize__() and __validate__() with underscores so they do not overlap with outer + // scope imported with `use super::*`. + #fn_sanitize + #fn_validate } ) } fn gen_new_without_validation( type_name: &TypeName, + generics: &Generics, inner_type: &Self::InnerType, sanitizers: &[Self::Sanitizer], ) -> TokenStream { - let sanitize = Self::gen_fn_sanitize(inner_type, sanitizers); + let fn_sanitize = Self::gen_fn_sanitize(inner_type, sanitizers); let (input_type, convert_raw_value_if_necessary) = if Self::NEW_CONVERT_INTO_INNER_TYPE { ( @@ -242,34 +248,37 @@ pub trait GenerateNewtype { }; quote!( - impl #type_name { + impl #generics #type_name #generics { pub fn new(raw_value: #input_type) -> Self { - #sanitize - #convert_raw_value_if_necessary - - Self(sanitize(raw_value)) + Self(Self::__sanitize__(raw_value)) } + // Definite associated private function __sanitize__() with underscores so they do not overlap with outer + // scope imported with `use super::*`. + #fn_sanitize } ) } fn gen_implementation( type_name: &TypeName, + generics: &Generics, inner_type: &Self::InnerType, guard: &Guard, new_unchecked: NewUnchecked, ) -> TokenStream { let impl_new = match guard { Guard::WithoutValidation { sanitizers } => { - Self::gen_new_without_validation(type_name, inner_type, sanitizers) + Self::gen_new_without_validation(type_name, generics, inner_type, sanitizers) } Guard::WithValidation { sanitizers, validators, - } => Self::gen_new_with_validation(type_name, inner_type, sanitizers, validators), + } => Self::gen_new_with_validation( + type_name, generics, inner_type, sanitizers, validators, + ), }; - let impl_into_inner = gen_impl_into_inner(type_name, inner_type); + let impl_into_inner = gen_impl_into_inner(type_name, generics, inner_type); let impl_new_unchecked = gen_new_unchecked(type_name, inner_type, new_unchecked); quote! { @@ -296,11 +305,12 @@ pub trait GenerateNewtype { new_unchecked, maybe_default_value, inner_type, + generics, } = params; let module_name = gen_module_name_for_type(&type_name); let implementation = - Self::gen_implementation(&type_name, &inner_type, &guard, new_unchecked); + Self::gen_implementation(&type_name, &generics, &inner_type, &guard, new_unchecked); let maybe_error_type_name: Option = match guard { Guard::WithoutValidation { .. } => None, @@ -349,7 +359,7 @@ pub trait GenerateNewtype { #(#doc_attrs)* #derive_transparent_traits - pub struct #type_name(#inner_type); + pub struct #type_name #generics(#inner_type); #implementation #implement_traits diff --git a/nutype_macros/src/common/models.rs b/nutype_macros/src/common/models.rs index be8b53f..e212b95 100644 --- a/nutype_macros/src/common/models.rs +++ b/nutype_macros/src/common/models.rs @@ -1,6 +1,7 @@ use kinded::Kinded; use std::ops::Add; use std::{collections::HashSet, fmt::Debug}; +use syn::Generics; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; @@ -158,6 +159,7 @@ pub struct Meta { pub inner_type: InnerType, pub vis: syn::Visibility, pub doc_attrs: Vec, + pub generics: Generics, } impl Meta { @@ -167,10 +169,12 @@ impl Meta { type_name, inner_type, vis, + generics, } = self; let typed_meta = TypedMeta { doc_attrs, type_name, + generics, attrs, vis, }; @@ -189,6 +193,7 @@ pub struct TypedMeta { pub vis: syn::Visibility, pub doc_attrs: Vec, + pub generics: Generics, } /// Validated model, that represents precisely what needs to be generated. @@ -342,6 +347,7 @@ pub struct GenerateParams { pub traits: HashSet, pub vis: syn::Visibility, pub type_name: TypeName, + pub generics: Generics, pub guard: Guard, pub new_unchecked: NewUnchecked, pub maybe_default_value: Option, @@ -381,6 +387,7 @@ pub trait Newtype { type_name, attrs, vis, + generics, } = typed_meta; let Attributes { guard, @@ -394,6 +401,7 @@ pub trait Newtype { traits, vis, type_name, + generics, guard, new_unchecked, maybe_default_value, diff --git a/nutype_macros/src/common/parse/meta.rs b/nutype_macros/src/common/parse/meta.rs index a3d4932..3a38968 100644 --- a/nutype_macros/src/common/parse/meta.rs +++ b/nutype_macros/src/common/parse/meta.rs @@ -22,7 +22,7 @@ pub fn parse_meta(token_stream: TokenStream) -> Result { data, vis, ident: type_name, - generics: _, + generics, } = input; let type_name = TypeName::new(type_name); @@ -100,6 +100,7 @@ pub fn parse_meta(token_stream: TokenStream) -> Result { Ok(Meta { doc_attrs, type_name, + generics, inner_type, vis, }) diff --git a/nutype_macros/src/float/gen/mod.rs b/nutype_macros/src/float/gen/mod.rs index 4dda353..a839f46 100644 --- a/nutype_macros/src/float/gen/mod.rs +++ b/nutype_macros/src/float/gen/mod.rs @@ -56,7 +56,7 @@ where .collect(); quote!( - fn sanitize(mut value: #inner_type) -> #inner_type { + fn __sanitize__(mut value: #inner_type) -> #inner_type { #transformations value } @@ -119,7 +119,7 @@ where .collect(); quote!( - fn validate(val: &#inner_type) -> core::result::Result<(), #error_name> { + fn __validate__(val: &#inner_type) -> core::result::Result<(), #error_name> { let val = *val; #validations Ok(()) diff --git a/nutype_macros/src/integer/gen/mod.rs b/nutype_macros/src/integer/gen/mod.rs index ca68ecd..a804a68 100644 --- a/nutype_macros/src/integer/gen/mod.rs +++ b/nutype_macros/src/integer/gen/mod.rs @@ -55,7 +55,7 @@ where .collect(); quote!( - fn sanitize(mut value: #inner_type) -> #inner_type { + fn __sanitize__(mut value: #inner_type) -> #inner_type { #transformations value } @@ -111,7 +111,7 @@ where .collect(); quote!( - fn validate(val: &#inner_type) -> ::core::result::Result<(), #error_name> { + fn __validate__(val: &#inner_type) -> ::core::result::Result<(), #error_name> { let val = *val; #validations Ok(()) diff --git a/nutype_macros/src/string/gen/mod.rs b/nutype_macros/src/string/gen/mod.rs index c5305c8..46a17ae 100644 --- a/nutype_macros/src/string/gen/mod.rs +++ b/nutype_macros/src/string/gen/mod.rs @@ -71,7 +71,7 @@ impl GenerateNewtype for StringNewtype { .collect(); quote!( - fn sanitize(value: String) -> String { + fn __sanitize__(value: String) -> String { #transformations value } @@ -158,7 +158,7 @@ impl GenerateNewtype for StringNewtype { }; quote!( - fn validate(val: &str) -> ::core::result::Result<(), #error_name> { + fn __validate__(val: &str) -> ::core::result::Result<(), #error_name> { #chars_count_if_required #validations Ok(()) From 6d5e676c201602d4ca19e7e76f19d922995483b7 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Fri, 31 May 2024 21:57:20 +0200 Subject: [PATCH 02/12] Fix clippy --- dummy/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dummy/src/main.rs b/dummy/src/main.rs index 606991c..7a78a95 100644 --- a/dummy/src/main.rs +++ b/dummy/src/main.rs @@ -2,7 +2,7 @@ use nutype::nutype; #[nutype( sanitize(with = |v| v), - validate(predicate = |v| v.len() > 0) + validate(predicate = |v| !v.is_empty() ) )] struct NonEmptyVec(Vec); From fbfb7e846562093ca2f02af96199ccf8fae9986f Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 00:28:41 +0200 Subject: [PATCH 03/12] Add an example with a newtype with generics --- CHANGELOG.md | 5 ++ Cargo.lock | 7 +++ Cargo.toml | 2 +- examples/any_generics/Cargo.toml | 9 +++ examples/any_generics/src/main.rs | 30 +++++++++ test_suite/tests/any.rs | 101 ++++++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 examples/any_generics/Cargo.toml create mode 100644 examples/any_generics/src/main.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 19146e3..fa67e29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### v0.x.x - 2024-xx-xx + +* Support newtypes with generics + + ### v0.4.2 - 2024-04-07 * Support `no_std` ( the dependency needs to be declared as `nutype = { default-features = false }` ) diff --git a/Cargo.lock b/Cargo.lock index 5dfd04c..bd7e639 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,13 @@ dependencies = [ "nutype", ] +[[package]] +name = "any_generics" +version = "0.1.0" +dependencies = [ + "nutype", +] + [[package]] name = "arbitrary" version = "1.3.2" diff --git a/Cargo.toml b/Cargo.toml index 11ea57d..8a3b4bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,5 @@ members = [ "examples/serde_complex", "examples/string_bounded_len", "examples/string_regex_email", - "examples/string_arbitrary", + "examples/string_arbitrary", "examples/any_generics", ] diff --git a/examples/any_generics/Cargo.toml b/examples/any_generics/Cargo.toml new file mode 100644 index 0000000..10a487c --- /dev/null +++ b/examples/any_generics/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "any_generics" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nutype = { path = "../../nutype" } diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs new file mode 100644 index 0000000..a73e816 --- /dev/null +++ b/examples/any_generics/src/main.rs @@ -0,0 +1,30 @@ +use nutype::nutype; +use std::borrow::Cow; + +#[nutype( + validate(predicate = |vec| !vec.is_empty()), + derive(Debug), +)] +struct NotEmpty(Vec); + +#[nutype( + derive(Debug), + validate(predicate = |s| s.len() > 3), +)] +struct Clarabelle<'b>(Cow<'b, str>); + +fn main() { + { + let v = NotEmpty::new(vec![1, 2, 3]).unwrap(); + assert_eq!(v.into_inner(), vec![1, 2, 3]); + } + { + let err = NotEmpty::::new(vec![]).unwrap_err(); + assert_eq!(err, NotEmptyError::PredicateViolated); + } + + { + let c1 = Clarabelle::new(Cow::Borrowed("Muu")).unwrap(); + assert_eq!(c1.into_inner(), Cow::Borrowed("Muu")); + } +} diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index c588ed9..38909d5 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -382,3 +382,104 @@ mod new_unchecked { assert_eq!(line_point.into_inner(), Point::new(3, 4)); } } + +#[cfg(test)] +mod with_generics { + use super::*; + + #[test] + fn test_generic_with_validate() { + #[nutype( + validate(predicate = |v| !v.is_empty()), + derive(Debug) + )] + struct NonEmptyVec(Vec); + + { + let vec = NonEmptyVec::new(vec![1, 2, 3]).unwrap(); + assert_eq!(vec.into_inner(), vec![1, 2, 3]); + } + + { + let vec = NonEmptyVec::new(vec![5]).unwrap(); + assert_eq!(vec.into_inner(), vec![5]); + } + + { + let vec: Vec = vec![]; + let err = NonEmptyVec::new(vec).unwrap_err(); + assert_eq!(err, NonEmptyVecError::PredicateViolated); + } + } + + #[test] + fn test_generic_with_sanitize() { + #[nutype( + sanitize(with = |mut v| { v.truncate(2); v }), + derive(Debug) + )] + struct UpToTwo(Vec); + + { + let vec = UpToTwo::new(vec![1, 2, 3]); + assert_eq!(vec.into_inner(), vec![1, 2]); + } + + { + let vec = UpToTwo::new(vec![5]); + assert_eq!(vec.into_inner(), vec![5]); + } + } + + #[test] + fn test_generic_with_sanitize_and_validate() { + #[nutype( + sanitize(with = |mut v| { v.truncate(2); v }), + validate(predicate = |v| !v.is_empty()), + derive(Debug) + )] + struct OneOrTwo(Vec); + + { + let vec = OneOrTwo::new(vec![1, 2, 3]).unwrap(); + assert_eq!(vec.into_inner(), vec![1, 2]); + } + + { + let vec = OneOrTwo::new(vec![5]).unwrap(); + assert_eq!(vec.into_inner(), vec![5]); + } + + { + let vec: Vec = vec![]; + let err = OneOrTwo::new(vec).unwrap_err(); + assert_eq!(err, OneOrTwoError::PredicateViolated); + } + } + + // TODO + // #[test] + // fn test_generic_with_boundaries_and_sanitize() { + // #[nutype( + // sanitize(with = |v| { v.sort(); v }), + // derive(Debug) + // )] + // struct SortedVec(Vec); + + // { + // let vec = NonEmptyVec::new(vec![1, 2, 3]).unwrap(); + // assert_eq!(vec.into_inner(), vec![1, 2, 3]); + // } + + // { + // let vec = NonEmptyVec::new(vec![5]).unwrap(); + // assert_eq!(vec.into_inner(), vec![5]); + // } + + // { + // let vec: Vec = vec![]; + // let err = NonEmptyVec::new(vec).unwrap_err(); + // assert_eq!(err, NonEmptyVecError::PredicateViolated); + // } + // } +} From 7aa7a8a1024a9516d554429f59dd3688bedcde20 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 00:43:15 +0200 Subject: [PATCH 04/12] Fix any_generics example --- examples/any_generics/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index a73e816..01118a8 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -9,7 +9,7 @@ struct NotEmpty(Vec); #[nutype( derive(Debug), - validate(predicate = |s| s.len() > 3), + validate(predicate = |s| s.len() >= 3), )] struct Clarabelle<'b>(Cow<'b, str>); From 6aa60e0132ac9de67e9e37eebfa183e247294378 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 14:32:36 +0200 Subject: [PATCH 05/12] Improve generics with lifetimes --- dummy/src/main.rs | 6 +++--- examples/any_generics/src/main.rs | 7 ++----- nutype_macros/src/any/gen/mod.rs | 17 +++++++++++++++-- test_suite/tests/any.rs | 20 ++++++++++++++++++++ 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/dummy/src/main.rs b/dummy/src/main.rs index 7a78a95..4fcf883 100644 --- a/dummy/src/main.rs +++ b/dummy/src/main.rs @@ -1,9 +1,9 @@ use nutype::nutype; +use std::borrow::Cow; #[nutype( - sanitize(with = |v| v), - validate(predicate = |v| !v.is_empty() ) + validate(predicate = |s| s.len() >= 3), )] -struct NonEmptyVec(Vec); +struct Clarabelle<'a>(Cow<'a, str>); fn main() {} diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index 01118a8..e11a7c1 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -7,10 +7,7 @@ use std::borrow::Cow; )] struct NotEmpty(Vec); -#[nutype( - derive(Debug), - validate(predicate = |s| s.len() >= 3), -)] +#[nutype(derive(Debug))] struct Clarabelle<'b>(Cow<'b, str>); fn main() { @@ -24,7 +21,7 @@ fn main() { } { - let c1 = Clarabelle::new(Cow::Borrowed("Muu")).unwrap(); + let c1 = Clarabelle::new(Cow::Borrowed("Muu")); assert_eq!(c1.into_inner(), Cow::Borrowed("Muu")); } } diff --git a/nutype_macros/src/any/gen/mod.rs b/nutype_macros/src/any/gen/mod.rs index 6feacec..e092d74 100644 --- a/nutype_macros/src/any/gen/mod.rs +++ b/nutype_macros/src/any/gen/mod.rs @@ -72,7 +72,7 @@ impl GenerateNewtype for AnyNewtype { .map(|validator| match validator { AnyValidator::Predicate(predicate) => { let inner_type_ref: syn::Type = parse_quote!( - &'a #inner_type + &'nutype_a #inner_type ); let typed_predicate: TypedCustomFunction = predicate .clone() @@ -88,7 +88,20 @@ impl GenerateNewtype for AnyNewtype { .collect(); quote!( - fn __validate__<'a>(val: &'a #inner_type) -> ::core::result::Result<(), #error_name> { + // NOTE 1: we're using a unique lifetime name `nutype_a` in a hope that it will not clash + // with any other lifetimes in the user's code. + // + // NOTE 2: + // When inner type is Cow<'a, str>, the generated code will look like this (with 2 + // lifetimes): + // + // fn __validate__<'nutype_a>(val: &'nutype_a Cow<'a, str>) + // + // Clippy does not like passing a reference to a Cow. So we need to ignore the `clippy::ptr_arg` warning. + // Since this code is generic which is used for different inner types (not only Cow), we cannot easily fix it to make + // clippy happy. + #[allow(clippy::ptr_arg)] + fn __validate__<'nutype_a>(val: &'nutype_a #inner_type) -> ::core::result::Result<(), #error_name> { #validations Ok(()) } diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index 38909d5..08d03ff 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -1,4 +1,5 @@ use nutype::nutype; +use std::borrow::Cow; use test_suite::test_helpers::traits::*; // Inner custom type, which is unknown to nutype @@ -482,4 +483,23 @@ mod with_generics { // assert_eq!(err, NonEmptyVecError::PredicateViolated); // } // } + + #[test] + fn test_generic_with_lifetime_cow() { + #[nutype( + validate(predicate = |s| s.len() >= 3), + derive(Debug) + )] + struct Clarabelle<'a>(Cow<'a, str>); + + { + let clarabelle = Clarabelle::new(Cow::Borrowed("Clarabelle")).unwrap(); + assert_eq!(clarabelle.into_inner(), Cow::Borrowed("Clarabelle")); + } + + { + let err = Clarabelle::new(Cow::Borrowed("Mu")).unwrap_err(); + assert_eq!(err, ClarabelleError::PredicateViolated); + } + } } From 5b6548cba91d20673b271c445d74b90d77eb5cbc Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 15:19:35 +0200 Subject: [PATCH 06/12] Make it possible to derive Display for Cow inner type --- dummy/src/main.rs | 9 +++++---- examples/any_generics/src/main.rs | 6 +++--- nutype_macros/src/any/gen/mod.rs | 4 +++- nutype_macros/src/any/gen/traits/mod.rs | 5 ++++- nutype_macros/src/common/gen/mod.rs | 2 ++ nutype_macros/src/common/gen/traits.rs | 5 +++-- nutype_macros/src/float/gen/mod.rs | 2 ++ nutype_macros/src/float/gen/traits/mod.rs | 3 ++- nutype_macros/src/integer/gen/mod.rs | 2 ++ nutype_macros/src/integer/gen/traits/mod.rs | 3 ++- nutype_macros/src/string/gen/mod.rs | 2 ++ nutype_macros/src/string/gen/traits/mod.rs | 3 ++- test_suite/tests/any.rs | 10 ++++------ 13 files changed, 36 insertions(+), 20 deletions(-) diff --git a/dummy/src/main.rs b/dummy/src/main.rs index 4fcf883..51a5277 100644 --- a/dummy/src/main.rs +++ b/dummy/src/main.rs @@ -1,9 +1,10 @@ use nutype::nutype; use std::borrow::Cow; -#[nutype( - validate(predicate = |s| s.len() >= 3), -)] +#[nutype(derive(Debug, Display))] struct Clarabelle<'a>(Cow<'a, str>); -fn main() {} +fn main() { + let clarabelle = Clarabelle::new(Cow::Borrowed("Clarabelle")); + assert_eq!(clarabelle.to_string(), "Clarabelle"); +} diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index e11a7c1..5ad7975 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -7,7 +7,7 @@ use std::borrow::Cow; )] struct NotEmpty(Vec); -#[nutype(derive(Debug))] +#[nutype(derive(Debug, Display))] struct Clarabelle<'b>(Cow<'b, str>); fn main() { @@ -21,7 +21,7 @@ fn main() { } { - let c1 = Clarabelle::new(Cow::Borrowed("Muu")); - assert_eq!(c1.into_inner(), Cow::Borrowed("Muu")); + let muu = Clarabelle::new(Cow::Borrowed("Muu")); + assert_eq!(muu.to_string(), "Muu"); } } diff --git a/nutype_macros/src/any/gen/mod.rs b/nutype_macros/src/any/gen/mod.rs index e092d74..75f9876 100644 --- a/nutype_macros/src/any/gen/mod.rs +++ b/nutype_macros/src/any/gen/mod.rs @@ -5,7 +5,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::quote; -use syn::parse_quote; +use syn::{parse_quote, Generics}; use crate::common::{ gen::{ @@ -117,6 +117,7 @@ impl GenerateNewtype for AnyNewtype { fn gen_traits( type_name: &TypeName, + generics: &Generics, inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, @@ -125,6 +126,7 @@ impl GenerateNewtype for AnyNewtype { ) -> Result { gen_traits( type_name, + generics, inner_type, maybe_error_type_name, traits, diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index 71e9e05..465fcd2 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -107,6 +107,7 @@ enum AnyIrregularTrait { pub fn gen_traits( type_name: &TypeName, + generics: &syn::Generics, inner_type: &AnyInnerType, maybe_error_type_name: Option, traits: HashSet, @@ -126,6 +127,7 @@ pub fn gen_traits( let implement_traits = gen_implemented_traits( type_name, + generics, inner_type, maybe_error_type_name, irregular_traits, @@ -141,6 +143,7 @@ pub fn gen_traits( fn gen_implemented_traits( type_name: &TypeName, + generics: &syn::Generics, inner_type: &AnyInnerType, maybe_error_type_name: Option, impl_traits: Vec, @@ -153,7 +156,7 @@ fn gen_implemented_traits( AnyIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), AnyIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), AnyIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, inner_type.clone())), - AnyIrregularTrait::Display => Ok(gen_impl_trait_display(type_name)), + AnyIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), AnyIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, inner_type)), AnyIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), AnyIrregularTrait::FromStr => Ok( diff --git a/nutype_macros/src/common/gen/mod.rs b/nutype_macros/src/common/gen/mod.rs index 7232533..09202be 100644 --- a/nutype_macros/src/common/gen/mod.rs +++ b/nutype_macros/src/common/gen/mod.rs @@ -182,6 +182,7 @@ pub trait GenerateNewtype { fn gen_traits( type_name: &TypeName, + generics: &Generics, inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, @@ -345,6 +346,7 @@ pub trait GenerateNewtype { implement_traits, } = Self::gen_traits( &type_name, + &generics, &inner_type, maybe_error_type_name, traits, diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 14ec3d7..1f42780 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use syn::Generics; use crate::common::models::{ErrorTypeName, InnerType, TypeName}; @@ -92,9 +93,9 @@ pub fn gen_impl_trait_deref(type_name: &TypeName, inner_type: impl ToTokens) -> } } -pub fn gen_impl_trait_display(type_name: &TypeName) -> TokenStream { +pub fn gen_impl_trait_display(type_name: &TypeName, generics: &Generics) -> TokenStream { quote! { - impl ::core::fmt::Display for #type_name { + impl #generics ::core::fmt::Display for #type_name #generics { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { // A tiny wrapper function with trait boundary that improves error reporting. diff --git a/nutype_macros/src/float/gen/mod.rs b/nutype_macros/src/float/gen/mod.rs index a839f46..e0703ff 100644 --- a/nutype_macros/src/float/gen/mod.rs +++ b/nutype_macros/src/float/gen/mod.rs @@ -5,6 +5,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use syn::Generics; use self::error::gen_validation_error_type; use super::{ @@ -136,6 +137,7 @@ where fn gen_traits( type_name: &TypeName, + _generics: &Generics, inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index 324f1b4..df2cd1f 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -3,6 +3,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use syn::Generics; use crate::{ common::{ @@ -176,7 +177,7 @@ fn gen_implemented_traits( Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } FloatIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), - FloatIrregularTrait::Display => Ok(gen_impl_trait_display(type_name)), + FloatIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, &Generics::default())), FloatIrregularTrait::Default => match maybe_default_value { Some(ref default_value) => { let has_validation = maybe_error_type_name.is_some(); diff --git a/nutype_macros/src/integer/gen/mod.rs b/nutype_macros/src/integer/gen/mod.rs index a804a68..0189bf4 100644 --- a/nutype_macros/src/integer/gen/mod.rs +++ b/nutype_macros/src/integer/gen/mod.rs @@ -5,6 +5,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use syn::Generics; use self::{error::gen_validation_error_type, traits::gen_traits}; use super::{ @@ -128,6 +129,7 @@ where fn gen_traits( type_name: &TypeName, + _generics: &Generics, inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, diff --git a/nutype_macros/src/integer/gen/traits/mod.rs b/nutype_macros/src/integer/gen/traits/mod.rs index 8c74ceb..4989d52 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -4,6 +4,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use syn::Generics; use crate::{ common::{ @@ -196,7 +197,7 @@ fn gen_implemented_traits( Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } IntegerIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), - IntegerIrregularTrait::Display => Ok(gen_impl_trait_display(type_name)), + IntegerIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, &Generics::default())), IntegerIrregularTrait::Default => { match maybe_default_value { Some(ref default_value) => { diff --git a/nutype_macros/src/string/gen/mod.rs b/nutype_macros/src/string/gen/mod.rs index 46a17ae..c85a7dd 100644 --- a/nutype_macros/src/string/gen/mod.rs +++ b/nutype_macros/src/string/gen/mod.rs @@ -6,6 +6,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::quote; +use syn::Generics; use crate::{ common::{ @@ -175,6 +176,7 @@ impl GenerateNewtype for StringNewtype { fn gen_traits( type_name: &TypeName, + _generics: &Generics, _inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, diff --git a/nutype_macros/src/string/gen/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index 42ad88b..6335156 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -4,6 +4,7 @@ use std::collections::HashSet; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use syn::Generics; use crate::{ common::{ @@ -190,7 +191,7 @@ fn gen_implemented_traits( Ok(gen_impl_try_from(type_name, maybe_error_type_name.as_ref())) } StringIrregularTrait::Borrow => Ok(gen_impl_borrow_str_and_string(type_name)), - StringIrregularTrait::Display => Ok(gen_impl_trait_display(type_name)), + StringIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, &Generics::default())), StringIrregularTrait::Default => match maybe_default_value { Some(ref default_value) => { let has_validation = maybe_error_type_name.is_some(); diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index 08d03ff..f3a5b27 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -488,18 +488,16 @@ mod with_generics { fn test_generic_with_lifetime_cow() { #[nutype( validate(predicate = |s| s.len() >= 3), - derive(Debug) + derive(Debug, Display) )] struct Clarabelle<'a>(Cow<'a, str>); { let clarabelle = Clarabelle::new(Cow::Borrowed("Clarabelle")).unwrap(); - assert_eq!(clarabelle.into_inner(), Cow::Borrowed("Clarabelle")); - } + assert_eq!(clarabelle.to_string(), "Clarabelle"); - { - let err = Clarabelle::new(Cow::Borrowed("Mu")).unwrap_err(); - assert_eq!(err, ClarabelleError::PredicateViolated); + let muu = Clarabelle::new(Cow::Owned("Muu".to_string())).unwrap(); + assert_eq!(muu.to_string(), "Muu"); } } } From ba09d5257ce67d2e32371c835123ba5428a4bdc2 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 15:41:00 +0200 Subject: [PATCH 07/12] Allow Cow inner type to derive Into --- nutype_macros/src/any/gen/traits/mod.rs | 2 +- nutype_macros/src/common/gen/traits.rs | 10 +++++++--- nutype_macros/src/float/gen/traits/mod.rs | 2 +- nutype_macros/src/integer/gen/traits/mod.rs | 2 +- nutype_macros/src/string/gen/traits/mod.rs | 2 +- test_suite/tests/any.rs | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index 465fcd2..8976a48 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -155,7 +155,7 @@ fn gen_implemented_traits( .map(|t| match t { AnyIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), AnyIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), - AnyIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, inner_type.clone())), + AnyIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type.clone())), AnyIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), AnyIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, inner_type)), AnyIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 1f42780..33dd5fe 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -52,7 +52,11 @@ where } } -pub fn gen_impl_trait_into(type_name: &TypeName, inner_type: impl Into) -> TokenStream { +pub fn gen_impl_trait_into( + type_name: &TypeName, + generics: &Generics, + inner_type: impl Into, +) -> TokenStream { let inner_type: InnerType = inner_type.into(); // NOTE: We're getting blank implementation of @@ -60,9 +64,9 @@ pub fn gen_impl_trait_into(type_name: &TypeName, inner_type: impl Into for Inner quote! { - impl ::core::convert::From<#type_name> for #inner_type { + impl #generics ::core::convert::From<#type_name #generics> for #inner_type { #[inline] - fn from(value: #type_name) -> Self { + fn from(value: #type_name #generics) -> Self { value.into_inner() } } diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index df2cd1f..98031ba 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -172,7 +172,7 @@ fn gen_implemented_traits( Ok(gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref())) } FloatIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), - FloatIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, inner_type)), + FloatIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, &Generics::default(), inner_type)), FloatIrregularTrait::TryFrom => { Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } diff --git a/nutype_macros/src/integer/gen/traits/mod.rs b/nutype_macros/src/integer/gen/traits/mod.rs index 4989d52..46f3b1c 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -192,7 +192,7 @@ fn gen_implemented_traits( Ok(gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref())) } IntegerIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), - IntegerIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, inner_type)), + IntegerIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, &Generics::default(), inner_type)), IntegerIrregularTrait::TryFrom => { Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } diff --git a/nutype_macros/src/string/gen/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index 6335156..c0a6f7f 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -186,7 +186,7 @@ fn gen_implemented_traits( Ok(gen_impl_from_str(type_name, maybe_error_type_name.as_ref())) } StringIrregularTrait::From => Ok(gen_impl_from_str_and_string(type_name)), - StringIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, inner_type)), + StringIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, &Generics::default(), inner_type)), StringIrregularTrait::TryFrom => { Ok(gen_impl_try_from(type_name, maybe_error_type_name.as_ref())) } diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index f3a5b27..f561aa6 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -488,7 +488,7 @@ mod with_generics { fn test_generic_with_lifetime_cow() { #[nutype( validate(predicate = |s| s.len() >= 3), - derive(Debug, Display) + derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into) )] struct Clarabelle<'a>(Cow<'a, str>); From 2a044edbf48325832d6053dc0d57cb42b848b605 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 15:48:11 +0200 Subject: [PATCH 08/12] Make it possible to derive From for Cow inner type --- dummy/src/main.rs | 6 ++--- examples/any_generics/src/main.rs | 27 ++++++++++++++++++++- nutype_macros/src/any/gen/traits/mod.rs | 2 +- nutype_macros/src/common/gen/traits.rs | 8 ++++-- nutype_macros/src/float/gen/mod.rs | 3 ++- nutype_macros/src/float/gen/traits/mod.rs | 9 ++++--- nutype_macros/src/integer/gen/mod.rs | 3 ++- nutype_macros/src/integer/gen/traits/mod.rs | 9 ++++--- nutype_macros/src/string/gen/traits/mod.rs | 5 ++-- test_suite/tests/any.rs | 1 + 10 files changed, 56 insertions(+), 17 deletions(-) diff --git a/dummy/src/main.rs b/dummy/src/main.rs index 51a5277..44259ec 100644 --- a/dummy/src/main.rs +++ b/dummy/src/main.rs @@ -1,10 +1,10 @@ use nutype::nutype; use std::borrow::Cow; -#[nutype(derive(Debug, Display))] +#[nutype(derive(Into))] struct Clarabelle<'a>(Cow<'a, str>); fn main() { - let clarabelle = Clarabelle::new(Cow::Borrowed("Clarabelle")); - assert_eq!(clarabelle.to_string(), "Clarabelle"); + // let clarabelle = Clarabelle::new(Cow::Borrowed("Clarabelle")); + // assert_eq!(clarabelle.to_string(), "Clarabelle"); } diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index 5ad7975..988a00d 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -7,7 +7,32 @@ use std::borrow::Cow; )] struct NotEmpty(Vec); -#[nutype(derive(Debug, Display))] +#[nutype(derive( + Debug, + Display, + Clone, + // Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + + // TODO + // AsRef, + + Into, + From, + // Deref, + // Borrow, + // FromStr, + // TryFrom, + // Default, + + // SerdeSerialize, + // SerdeDeserialize, + // ArbitraryArbitrary, +))] struct Clarabelle<'b>(Cow<'b, str>); fn main() { diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index 8976a48..e719e78 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -154,7 +154,7 @@ fn gen_implemented_traits( .iter() .map(|t| match t { AnyIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), - AnyIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), + AnyIrregularTrait::From => Ok(gen_impl_trait_from(type_name, generics, inner_type)), AnyIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type.clone())), AnyIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), AnyIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, inner_type)), diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 33dd5fe..0d678a3 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -127,9 +127,13 @@ pub fn gen_impl_trait_borrow(type_name: &TypeName, borrowed_type: impl ToTokens) } } -pub fn gen_impl_trait_from(type_name: &TypeName, inner_type: impl ToTokens) -> TokenStream { +pub fn gen_impl_trait_from( + type_name: &TypeName, + generics: &Generics, + inner_type: impl ToTokens +) -> TokenStream { quote! { - impl ::core::convert::From<#inner_type> for #type_name { + impl #generics ::core::convert::From<#inner_type> for #type_name #generics { #[inline] fn from(raw_value: #inner_type) -> Self { Self::new(raw_value) diff --git a/nutype_macros/src/float/gen/mod.rs b/nutype_macros/src/float/gen/mod.rs index e0703ff..4833267 100644 --- a/nutype_macros/src/float/gen/mod.rs +++ b/nutype_macros/src/float/gen/mod.rs @@ -137,7 +137,7 @@ where fn gen_traits( type_name: &TypeName, - _generics: &Generics, + generics: &Generics, inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, @@ -146,6 +146,7 @@ where ) -> Result { gen_traits( type_name, + generics, inner_type, maybe_error_type_name, maybe_default_value, diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index 98031ba..408f112 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -123,6 +123,7 @@ impl ToTokens for FloatTransparentTrait { pub fn gen_traits( type_name: &TypeName, + generics: &Generics, inner_type: &FloatInnerType, maybe_error_type_name: Option, maybe_default_value: Option, @@ -142,6 +143,7 @@ pub fn gen_traits( let implement_traits = gen_implemented_traits( type_name, + generics, inner_type, maybe_error_type_name, maybe_default_value, @@ -157,6 +159,7 @@ pub fn gen_traits( fn gen_implemented_traits( type_name: &TypeName, + generics: &Generics, inner_type: &FloatInnerType, maybe_error_type_name: Option, maybe_default_value: Option, @@ -171,13 +174,13 @@ fn gen_implemented_traits( FloatIrregularTrait::FromStr => { Ok(gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref())) } - FloatIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), - FloatIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, &Generics::default(), inner_type)), + FloatIrregularTrait::From => Ok(gen_impl_trait_from(type_name, generics, inner_type)), + FloatIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type)), FloatIrregularTrait::TryFrom => { Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } FloatIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), - FloatIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, &Generics::default())), + FloatIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), FloatIrregularTrait::Default => match maybe_default_value { Some(ref default_value) => { let has_validation = maybe_error_type_name.is_some(); diff --git a/nutype_macros/src/integer/gen/mod.rs b/nutype_macros/src/integer/gen/mod.rs index 0189bf4..49746d5 100644 --- a/nutype_macros/src/integer/gen/mod.rs +++ b/nutype_macros/src/integer/gen/mod.rs @@ -129,7 +129,7 @@ where fn gen_traits( type_name: &TypeName, - _generics: &Generics, + generics: &Generics, inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, @@ -138,6 +138,7 @@ where ) -> Result { gen_traits( type_name, + generics, inner_type, maybe_error_type_name, traits, diff --git a/nutype_macros/src/integer/gen/traits/mod.rs b/nutype_macros/src/integer/gen/traits/mod.rs index 46f3b1c..26e8f19 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -24,6 +24,7 @@ type IntegerGeneratableTrait = GeneratableTrait( type_name: &TypeName, + generics: &Generics, inner_type: &IntegerInnerType, maybe_error_type_name: Option, traits: HashSet, @@ -43,6 +44,7 @@ pub fn gen_traits( let implement_traits = gen_implemented_traits( type_name, + generics, inner_type, maybe_error_type_name, irregular_traits, @@ -177,6 +179,7 @@ impl ToTokens for IntegerTransparentTrait { fn gen_implemented_traits( type_name: &TypeName, + generics: &Generics, inner_type: &IntegerInnerType, maybe_error_type_name: Option, impl_traits: Vec, @@ -191,13 +194,13 @@ fn gen_implemented_traits( IntegerIrregularTrait::FromStr => { Ok(gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref())) } - IntegerIrregularTrait::From => Ok(gen_impl_trait_from(type_name, inner_type)), - IntegerIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, &Generics::default(), inner_type)), + IntegerIrregularTrait::From => Ok(gen_impl_trait_from(type_name, generics, inner_type)), + IntegerIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type)), IntegerIrregularTrait::TryFrom => { Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } IntegerIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), - IntegerIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, &Generics::default())), + IntegerIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), IntegerIrregularTrait::Default => { match maybe_default_value { Some(ref default_value) => { diff --git a/nutype_macros/src/string/gen/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index c0a6f7f..294623a 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -250,8 +250,9 @@ fn gen_impl_from_str( } fn gen_impl_from_str_and_string(type_name: &TypeName) -> TokenStream { - let impl_from_string = gen_impl_trait_from(type_name, quote!(String)); - let impl_from_str = gen_impl_trait_from(type_name, quote!(&str)); + let generics = Generics::default(); + let impl_from_string = gen_impl_trait_from(type_name, &generics, quote!(String)); + let impl_from_str = gen_impl_trait_from(type_name, &generics, quote!(&str)); quote! { #impl_from_string diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index f561aa6..92a2511 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -488,6 +488,7 @@ mod with_generics { fn test_generic_with_lifetime_cow() { #[nutype( validate(predicate = |s| s.len() >= 3), + // TODO: derive TryFrom derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into) )] struct Clarabelle<'a>(Cow<'a, str>); From 6586edefcffd150a5f6ceb024b97c19fb786d092 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 15:55:05 +0200 Subject: [PATCH 09/12] Make it possible to derive Deref for generic inner type --- examples/any_generics/src/main.rs | 2 +- nutype_macros/src/any/gen/traits/mod.rs | 2 +- nutype_macros/src/common/gen/traits.rs | 10 +++++++--- nutype_macros/src/float/gen/traits/mod.rs | 2 +- nutype_macros/src/integer/gen/traits/mod.rs | 2 +- nutype_macros/src/string/gen/mod.rs | 3 ++- nutype_macros/src/string/gen/traits/mod.rs | 5 ++++- test_suite/tests/any.rs | 2 +- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index 988a00d..b0b8bca 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -23,7 +23,7 @@ struct NotEmpty(Vec); Into, From, - // Deref, + Deref, // Borrow, // FromStr, // TryFrom, diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index e719e78..59c6333 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -157,7 +157,7 @@ fn gen_implemented_traits( AnyIrregularTrait::From => Ok(gen_impl_trait_from(type_name, generics, inner_type)), AnyIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type.clone())), AnyIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), - AnyIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, inner_type)), + AnyIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, generics, inner_type)), AnyIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), AnyIrregularTrait::FromStr => Ok( gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref()) diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 0d678a3..692094b 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -84,9 +84,13 @@ pub fn gen_impl_trait_as_ref(type_name: &TypeName, inner_type: impl ToTokens) -> } } -pub fn gen_impl_trait_deref(type_name: &TypeName, inner_type: impl ToTokens) -> TokenStream { +pub fn gen_impl_trait_deref( + type_name: &TypeName, + generics: &Generics, + inner_type: impl ToTokens, +) -> TokenStream { quote! { - impl ::core::ops::Deref for #type_name { + impl #generics ::core::ops::Deref for #type_name #generics { type Target = #inner_type; #[inline] @@ -130,7 +134,7 @@ pub fn gen_impl_trait_borrow(type_name: &TypeName, borrowed_type: impl ToTokens) pub fn gen_impl_trait_from( type_name: &TypeName, generics: &Generics, - inner_type: impl ToTokens + inner_type: impl ToTokens, ) -> TokenStream { quote! { impl #generics ::core::convert::From<#inner_type> for #type_name #generics { diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index 408f112..b009d71 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -170,7 +170,7 @@ fn gen_implemented_traits( .iter() .map(|t| match t { FloatIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), - FloatIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, inner_type)), + FloatIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, generics, inner_type)), FloatIrregularTrait::FromStr => { Ok(gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref())) } diff --git a/nutype_macros/src/integer/gen/traits/mod.rs b/nutype_macros/src/integer/gen/traits/mod.rs index 26e8f19..c32e723 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -190,7 +190,7 @@ fn gen_implemented_traits( .iter() .map(|t| match t { IntegerIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), - IntegerIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, inner_type)), + IntegerIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, generics, inner_type)), IntegerIrregularTrait::FromStr => { Ok(gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref())) } diff --git a/nutype_macros/src/string/gen/mod.rs b/nutype_macros/src/string/gen/mod.rs index c85a7dd..7975ef0 100644 --- a/nutype_macros/src/string/gen/mod.rs +++ b/nutype_macros/src/string/gen/mod.rs @@ -176,7 +176,7 @@ impl GenerateNewtype for StringNewtype { fn gen_traits( type_name: &TypeName, - _generics: &Generics, + generics: &Generics, _inner_type: &Self::InnerType, maybe_error_type_name: Option, traits: HashSet, @@ -185,6 +185,7 @@ impl GenerateNewtype for StringNewtype { ) -> Result { gen_traits( type_name, + generics, maybe_error_type_name, traits, maybe_default_value, diff --git a/nutype_macros/src/string/gen/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index 294623a..151e93c 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -138,6 +138,7 @@ impl ToTokens for StringTransparentTrait { pub fn gen_traits( type_name: &TypeName, + generics: &Generics, maybe_error_type_name: Option, traits: HashSet, maybe_default_value: Option, @@ -156,6 +157,7 @@ pub fn gen_traits( let implement_traits = gen_implemented_traits( type_name, + generics, maybe_error_type_name, maybe_default_value, irregular_traits, @@ -170,6 +172,7 @@ pub fn gen_traits( fn gen_implemented_traits( type_name: &TypeName, + generics: &Generics, maybe_error_type_name: Option, maybe_default_value: Option, impl_traits: Vec, @@ -181,7 +184,7 @@ fn gen_implemented_traits( .iter() .map(|t| match t { StringIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, quote!(str))), - StringIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, quote!(String))), + StringIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, generics, quote!(String))), StringIrregularTrait::FromStr => { Ok(gen_impl_from_str(type_name, maybe_error_type_name.as_ref())) } diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index 92a2511..e8b67ac 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -489,7 +489,7 @@ mod with_generics { #[nutype( validate(predicate = |s| s.len() >= 3), // TODO: derive TryFrom - derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into) + derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into, Deref) )] struct Clarabelle<'a>(Cow<'a, str>); From fbf73dc10206acdae4de1b8de229b04dc58dc049 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 15:58:34 +0200 Subject: [PATCH 10/12] Make it possible to derive Borrow for an inner type with generics --- examples/any_generics/src/main.rs | 2 +- nutype_macros/src/any/gen/traits/mod.rs | 2 +- nutype_macros/src/common/gen/traits.rs | 8 ++++++-- nutype_macros/src/float/gen/traits/mod.rs | 2 +- nutype_macros/src/integer/gen/traits/mod.rs | 2 +- nutype_macros/src/string/gen/traits/mod.rs | 5 +++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index b0b8bca..bed214a 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -24,7 +24,7 @@ struct NotEmpty(Vec); Into, From, Deref, - // Borrow, + Borrow, // FromStr, // TryFrom, // Default, diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index 59c6333..f7133b6 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -158,7 +158,7 @@ fn gen_implemented_traits( AnyIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type.clone())), AnyIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), AnyIrregularTrait::Deref => Ok(gen_impl_trait_deref(type_name, generics, inner_type)), - AnyIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), + AnyIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, generics, inner_type)), AnyIrregularTrait::FromStr => Ok( gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref()) ), diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 692094b..5c912e3 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -120,9 +120,13 @@ pub fn gen_impl_trait_display(type_name: &TypeName, generics: &Generics) -> Toke } } -pub fn gen_impl_trait_borrow(type_name: &TypeName, borrowed_type: impl ToTokens) -> TokenStream { +pub fn gen_impl_trait_borrow( + type_name: &TypeName, + generics: &Generics, + borrowed_type: impl ToTokens, +) -> TokenStream { quote! { - impl ::core::borrow::Borrow<#borrowed_type> for #type_name { + impl #generics ::core::borrow::Borrow<#borrowed_type> for #type_name #generics { #[inline] fn borrow(&self) -> &#borrowed_type { &self.0 diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index b009d71..9ef402f 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -179,7 +179,7 @@ fn gen_implemented_traits( FloatIrregularTrait::TryFrom => { Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } - FloatIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), + FloatIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, generics, inner_type)), FloatIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), FloatIrregularTrait::Default => match maybe_default_value { Some(ref default_value) => { diff --git a/nutype_macros/src/integer/gen/traits/mod.rs b/nutype_macros/src/integer/gen/traits/mod.rs index c32e723..3bb25b8 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -199,7 +199,7 @@ fn gen_implemented_traits( IntegerIrregularTrait::TryFrom => { Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) } - IntegerIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, inner_type)), + IntegerIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, generics, inner_type)), IntegerIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), IntegerIrregularTrait::Default => { match maybe_default_value { diff --git a/nutype_macros/src/string/gen/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index 151e93c..a1e3741 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -278,8 +278,9 @@ fn gen_impl_try_from( } fn gen_impl_borrow_str_and_string(type_name: &TypeName) -> TokenStream { - let impl_borrow_string = gen_impl_trait_borrow(type_name, quote!(String)); - let impl_borrow_str = gen_impl_trait_borrow(type_name, quote!(str)); + let generics = Generics::default(); + let impl_borrow_string = gen_impl_trait_borrow(type_name, &generics, quote!(String)); + let impl_borrow_str = gen_impl_trait_borrow(type_name, &generics, quote!(str)); quote! { #impl_borrow_string From b0ed3e29d46efe785682d327c21e7002154530d1 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 16:07:12 +0200 Subject: [PATCH 11/12] Make it possible to derive TryFrom for an inner type with generics --- examples/any_generics/src/main.rs | 2 +- nutype_macros/src/any/gen/traits/mod.rs | 2 +- nutype_macros/src/common/gen/traits.rs | 9 +++++---- nutype_macros/src/float/gen/traits/mod.rs | 2 +- nutype_macros/src/integer/gen/traits/mod.rs | 2 +- nutype_macros/src/string/gen/traits/mod.rs | 6 ++++-- test_suite/tests/any.rs | 3 +-- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index bed214a..fbd979b 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -20,12 +20,12 @@ struct NotEmpty(Vec); // TODO // AsRef, + // FromStr, Into, From, Deref, Borrow, - // FromStr, // TryFrom, // Default, diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index f7133b6..0c80950 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -163,7 +163,7 @@ fn gen_implemented_traits( gen_impl_trait_from_str(type_name, inner_type, maybe_error_type_name.as_ref()) ), AnyIrregularTrait::TryFrom => Ok( - gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref()) + gen_impl_trait_try_from(type_name, generics, inner_type, maybe_error_type_name.as_ref()) ), AnyIrregularTrait::Default => match maybe_default_value { Some(ref default_value) => { diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 5c912e3..2ece351 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -152,6 +152,7 @@ pub fn gen_impl_trait_from( pub fn gen_impl_trait_try_from( type_name: &TypeName, + generics: &Generics, inner_type: impl ToTokens, maybe_error_type_name: Option<&ErrorTypeName>, ) -> TokenStream { @@ -160,11 +161,11 @@ pub fn gen_impl_trait_try_from( // The case when there are validation // quote! { - impl ::core::convert::TryFrom<#inner_type> for #type_name { + impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics { type Error = #error_type_name; #[inline] - fn try_from(raw_value: #inner_type) -> Result<#type_name, Self::Error> { + fn try_from(raw_value: #inner_type) -> Result<#type_name #generics, Self::Error> { Self::new(raw_value) } } @@ -174,11 +175,11 @@ pub fn gen_impl_trait_try_from( // The case when there are no validation // quote! { - impl ::core::convert::TryFrom<#inner_type> for #type_name { + impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics { type Error = ::core::convert::Infallible; #[inline] - fn try_from(raw_value: #inner_type) -> Result<#type_name, Self::Error> { + fn try_from(raw_value: #inner_type) -> Result<#type_name #generics, Self::Error> { Ok(Self::new(raw_value)) } } diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index 9ef402f..20bca68 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -177,7 +177,7 @@ fn gen_implemented_traits( FloatIrregularTrait::From => Ok(gen_impl_trait_from(type_name, generics, inner_type)), FloatIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type)), FloatIrregularTrait::TryFrom => { - Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) + Ok(gen_impl_trait_try_from(type_name, generics, inner_type, maybe_error_type_name.as_ref())) } FloatIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, generics, inner_type)), FloatIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), diff --git a/nutype_macros/src/integer/gen/traits/mod.rs b/nutype_macros/src/integer/gen/traits/mod.rs index 3bb25b8..c7fe088 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -197,7 +197,7 @@ fn gen_implemented_traits( IntegerIrregularTrait::From => Ok(gen_impl_trait_from(type_name, generics, inner_type)), IntegerIrregularTrait::Into => Ok(gen_impl_trait_into(type_name, generics, inner_type)), IntegerIrregularTrait::TryFrom => { - Ok(gen_impl_trait_try_from(type_name, inner_type, maybe_error_type_name.as_ref())) + Ok(gen_impl_trait_try_from(type_name, generics, inner_type, maybe_error_type_name.as_ref())) } IntegerIrregularTrait::Borrow => Ok(gen_impl_trait_borrow(type_name, generics, inner_type)), IntegerIrregularTrait::Display => Ok(gen_impl_trait_display(type_name, generics)), diff --git a/nutype_macros/src/string/gen/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index a1e3741..4896945 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -267,9 +267,11 @@ fn gen_impl_try_from( type_name: &TypeName, maybe_error_type_name: Option<&ErrorTypeName>, ) -> TokenStream { + let generics = Generics::default(); let impl_try_from_string = - gen_impl_trait_try_from(type_name, quote!(String), maybe_error_type_name); - let impl_try_from_str = gen_impl_trait_try_from(type_name, quote!(&str), maybe_error_type_name); + gen_impl_trait_try_from(type_name, &generics, quote!(String), maybe_error_type_name); + let impl_try_from_str = + gen_impl_trait_try_from(type_name, &generics, quote!(&str), maybe_error_type_name); quote! { #impl_try_from_string diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index e8b67ac..a30555d 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -488,8 +488,7 @@ mod with_generics { fn test_generic_with_lifetime_cow() { #[nutype( validate(predicate = |s| s.len() >= 3), - // TODO: derive TryFrom - derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into, Deref) + derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into, Deref, Borrow, TryFrom) )] struct Clarabelle<'a>(Cow<'a, str>); From 2cf037678c9cd6618426a02d80fa3c32e73dba20 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 16:44:25 +0200 Subject: [PATCH 12/12] Tiny changes in examples/any_generics/src/main.rs --- examples/any_generics/src/main.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index fbd979b..250a7f3 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -11,27 +11,23 @@ struct NotEmpty(Vec); Debug, Display, Clone, - // Copy, PartialEq, Eq, PartialOrd, Ord, Hash, - - // TODO - // AsRef, - // FromStr, - Into, From, Deref, Borrow, + // TODO + // AsRef, + // FromStr, // TryFrom, // Default, - - // SerdeSerialize, - // SerdeDeserialize, - // ArbitraryArbitrary, + // Serialize, + // Deserialize, + // Arbitrary, ))] struct Clarabelle<'b>(Cow<'b, str>);