From 346122e31c769529b7e75e9763e450acab307a44 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sun, 23 Jun 2024 12:37:18 +0200 Subject: [PATCH] Support derive(TryFrom) with generics --- nutype_macros/src/common/gen/traits.rs | 10 ++++--- test_suite/tests/any.rs | 36 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 8d863ab..ac525be 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -166,16 +166,18 @@ pub fn gen_impl_trait_try_from( inner_type: impl ToTokens, maybe_error_type_name: Option<&ErrorTypeName>, ) -> TokenStream { + let generics_without_bounds = strip_trait_bounds_on_generics(generics); + match maybe_error_type_name { Some(error_type_name) => { // The case when there are validation // quote! { - impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics { + impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics_without_bounds { type Error = #error_type_name; #[inline] - fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics, Self::Error> { + fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics_without_bounds, Self::Error> { Self::new(raw_value) } } @@ -185,11 +187,11 @@ pub fn gen_impl_trait_try_from( // The case when there are no validation // quote! { - impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics { + impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics_without_bounds { type Error = ::core::convert::Infallible; #[inline] - fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics, Self::Error> { + fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics_without_bounds, Self::Error> { Ok(Self::new(raw_value)) } } diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index 230ef23..733c5a7 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -665,9 +665,45 @@ mod with_generics { } } + #[test] + fn test_generic_boundaries_try_from_without_validation() { + // Note, that we get TryFrom thanks to the blanket implementation in core: + // + // impl TryFrom for T + // where + // U: Into + // + #[nutype(derive(Debug, From))] + struct Doener(T); + + let durum = Doener::try_from("Durum").unwrap(); + assert_eq!(durum.into_inner(), "Durum"); + } + + #[test] + fn test_generic_boundaries_try_from_with_validation() { + #[nutype( + derive(Debug, TryFrom), + validate(predicate = |v| !v.is_empty()) + )] + struct NotEmpty(Vec); + { + let err = NotEmpty::::try_from(vec![]).unwrap_err(); + assert_eq!(err, NotEmptyError::PredicateViolated); + } + { + let v = NotEmpty::try_from(vec![1, 2, 3]).unwrap(); + assert_eq!(v.into_inner(), vec![1, 2, 3]); + } + } + #[test] fn test_generic_boundaries_from_str() { // TODO + // #[nutype( + // derive(Debug, FromStr), + // )] + // struct Wrapper(T); } #[test]