From 5dd4efdc2cc0979c1a4f16f31ff42b3ce8d73da7 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sun, 2 Jun 2024 15:11:40 +0200 Subject: [PATCH] Derive AsRef on newtypes 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 | 2 +- test_suite/tests/any.rs | 30 ++++++++++++++++++++- 7 files changed, 40 insertions(+), 8 deletions(-) diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs index 250a7f3..8ef2774 100644 --- a/examples/any_generics/src/main.rs +++ b/examples/any_generics/src/main.rs @@ -20,8 +20,8 @@ struct NotEmpty(Vec); From, Deref, Borrow, + AsRef, // TODO - // AsRef, // FromStr, // TryFrom, // Default, diff --git a/nutype_macros/src/any/gen/traits/mod.rs b/nutype_macros/src/any/gen/traits/mod.rs index 0c80950..8e57da3 100644 --- a/nutype_macros/src/any/gen/traits/mod.rs +++ b/nutype_macros/src/any/gen/traits/mod.rs @@ -153,7 +153,7 @@ fn gen_implemented_traits( impl_traits .iter() .map(|t| match t { - AnyIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), + AnyIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, generics, 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)), diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs index 2ece351..52acbab 100644 --- a/nutype_macros/src/common/gen/traits.rs +++ b/nutype_macros/src/common/gen/traits.rs @@ -73,9 +73,13 @@ pub fn gen_impl_trait_into( } } -pub fn gen_impl_trait_as_ref(type_name: &TypeName, inner_type: impl ToTokens) -> TokenStream { +pub fn gen_impl_trait_as_ref( + type_name: &TypeName, + generics: &Generics, + inner_type: impl ToTokens, +) -> TokenStream { quote! { - impl ::core::convert::AsRef<#inner_type> for #type_name { + impl #generics ::core::convert::AsRef<#inner_type> for #type_name #generics { #[inline] fn as_ref(&self) -> &#inner_type { &self.0 diff --git a/nutype_macros/src/float/gen/traits/mod.rs b/nutype_macros/src/float/gen/traits/mod.rs index 20bca68..548315d 100644 --- a/nutype_macros/src/float/gen/traits/mod.rs +++ b/nutype_macros/src/float/gen/traits/mod.rs @@ -169,7 +169,7 @@ fn gen_implemented_traits( impl_traits .iter() .map(|t| match t { - FloatIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), + FloatIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, generics, 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 c7fe088..52106a2 100644 --- a/nutype_macros/src/integer/gen/traits/mod.rs +++ b/nutype_macros/src/integer/gen/traits/mod.rs @@ -189,7 +189,7 @@ fn gen_implemented_traits( impl_traits .iter() .map(|t| match t { - IntegerIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, inner_type)), + IntegerIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, generics, 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/traits/mod.rs b/nutype_macros/src/string/gen/traits/mod.rs index 4896945..5d9737c 100644 --- a/nutype_macros/src/string/gen/traits/mod.rs +++ b/nutype_macros/src/string/gen/traits/mod.rs @@ -183,7 +183,7 @@ fn gen_implemented_traits( impl_traits .iter() .map(|t| match t { - StringIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, quote!(str))), + StringIrregularTrait::AsRef => Ok(gen_impl_trait_as_ref(type_name, generics, quote!(str))), 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 a30555d..9c1fb60 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -1,5 +1,6 @@ use nutype::nutype; use std::borrow::Cow; +use std::collections::HashMap; use test_suite::test_helpers::traits::*; // Inner custom type, which is unknown to nutype @@ -488,7 +489,7 @@ mod with_generics { fn test_generic_with_lifetime_cow() { #[nutype( validate(predicate = |s| s.len() >= 3), - derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into, Deref, Borrow, TryFrom) + derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Into, Deref, Borrow, TryFrom, AsRef) )] struct Clarabelle<'a>(Cow<'a, str>); @@ -500,4 +501,31 @@ mod with_generics { assert_eq!(muu.to_string(), "Muu"); } } + + #[test] + fn test_derive_as_ref_with_generic() { + #[nutype(derive(AsRef))] + struct SquareMap(HashMap); + + let mut inner_map = HashMap::new(); + inner_map.insert(4, 16); + inner_map.insert(5, 25); + let squares = SquareMap::new(inner_map.clone()); + assert_eq!(squares.as_ref(), &inner_map); + } + + #[test] + fn test_derive_as_ref_with_generic_and_validation() { + #[nutype( + validate(predicate = |map| map.len() > 1), + derive(AsRef) + )] + struct NonEmptyMap(HashMap); + + let mut inner_map = HashMap::new(); + inner_map.insert(4, 16); + inner_map.insert(5, 25); + let squares = NonEmptyMap::new(inner_map.clone()).unwrap(); + assert_eq!(squares.as_ref(), &inner_map); + } }