Skip to content

Commit 91afd23

Browse files
authored
Merge pull request #148 from greyblake/generics-derive-try-from
Support derive(TryFrom) with generics
2 parents 240c7ed + 346122e commit 91afd23

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

nutype_macros/src/common/gen/traits.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,18 @@ pub fn gen_impl_trait_try_from(
166166
inner_type: impl ToTokens,
167167
maybe_error_type_name: Option<&ErrorTypeName>,
168168
) -> TokenStream {
169+
let generics_without_bounds = strip_trait_bounds_on_generics(generics);
170+
169171
match maybe_error_type_name {
170172
Some(error_type_name) => {
171173
// The case when there are validation
172174
//
173175
quote! {
174-
impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics {
176+
impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics_without_bounds {
175177
type Error = #error_type_name;
176178

177179
#[inline]
178-
fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics, Self::Error> {
180+
fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics_without_bounds, Self::Error> {
179181
Self::new(raw_value)
180182
}
181183
}
@@ -185,11 +187,11 @@ pub fn gen_impl_trait_try_from(
185187
// The case when there are no validation
186188
//
187189
quote! {
188-
impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics {
190+
impl #generics ::core::convert::TryFrom<#inner_type> for #type_name #generics_without_bounds {
189191
type Error = ::core::convert::Infallible;
190192

191193
#[inline]
192-
fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics, Self::Error> {
194+
fn try_from(raw_value: #inner_type) -> ::core::result::Result<#type_name #generics_without_bounds, Self::Error> {
193195
Ok(Self::new(raw_value))
194196
}
195197
}

test_suite/tests/any.rs

+36
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,45 @@ mod with_generics {
665665
}
666666
}
667667

668+
#[test]
669+
fn test_generic_boundaries_try_from_without_validation() {
670+
// Note, that we get TryFrom thanks to the blanket implementation in core:
671+
//
672+
// impl<T, U> TryFrom<U> for T
673+
// where
674+
// U: Into<T>
675+
//
676+
#[nutype(derive(Debug, From))]
677+
struct Doener<T>(T);
678+
679+
let durum = Doener::try_from("Durum").unwrap();
680+
assert_eq!(durum.into_inner(), "Durum");
681+
}
682+
683+
#[test]
684+
fn test_generic_boundaries_try_from_with_validation() {
685+
#[nutype(
686+
derive(Debug, TryFrom),
687+
validate(predicate = |v| !v.is_empty())
688+
)]
689+
struct NotEmpty<T>(Vec<T>);
690+
{
691+
let err = NotEmpty::<i32>::try_from(vec![]).unwrap_err();
692+
assert_eq!(err, NotEmptyError::PredicateViolated);
693+
}
694+
{
695+
let v = NotEmpty::try_from(vec![1, 2, 3]).unwrap();
696+
assert_eq!(v.into_inner(), vec![1, 2, 3]);
697+
}
698+
}
699+
668700
#[test]
669701
fn test_generic_boundaries_from_str() {
670702
// TODO
703+
// #[nutype(
704+
// derive(Debug, FromStr),
705+
// )]
706+
// struct Wrapper<T>(T);
671707
}
672708

673709
#[test]

0 commit comments

Comments
 (0)