From d838728b5953b94fb0f5c21e8f1ed639ae31f043 Mon Sep 17 00:00:00 2001 From: bluurryy <164359728+bluurryy@users.noreply.github.com> Date: Thu, 5 Sep 2024 23:18:53 +0200 Subject: [PATCH] Fix ambiguous associated item for `TryFrom`, `TryInto` and `FromStr` --- CHANGELOG.md | 1 + impl/doc/from_str.md | 6 +++--- impl/doc/try_into.md | 14 +++++++------- impl/src/from_str.rs | 7 ++++--- impl/src/try_from.rs | 6 ++++-- impl/src/try_into.rs | 8 ++++++-- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5029725c..60a79fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ([#399](https://github.com/JelteF/derive_more/pull/399)) - `unreachable_code` warnings on generated code when `!` (never type) is used. ([#404](https://github.com/JelteF/derive_more/pull/404)) +- Fix ambiguous associated item error when deriving `TryFrom`, `TryInto` or `FromStr` with an associated item called `Error` or `Err` respectively. ## 1.0.0 - 2024-08-07 diff --git a/impl/doc/from_str.md b/impl/doc/from_str.md index bf9d1e73..eaef5aad 100644 --- a/impl/doc/from_str.md +++ b/impl/doc/from_str.md @@ -46,7 +46,7 @@ Code like this will be generated: # struct MyInt(i32); impl derive_more::FromStr for MyInt { type Err = ::Err; - fn from_str(src: &str) -> Result { + fn from_str(src: &str) -> Result::Err> { return Ok(MyInt(i32::from_str(src)?)); } } @@ -76,7 +76,7 @@ Code like this will be generated: # } impl derive_more::FromStr for Point1D { type Err = ::Err; - fn from_str(src: &str) -> Result { + fn from_str(src: &str) -> Result::Err> { return Ok(Point1D { x: i32::from_str(src)?, }); @@ -123,7 +123,7 @@ Code like this will be generated: # impl derive_more::FromStr for EnumNoFields { type Err = derive_more::FromStrError; - fn from_str(src: &str) -> Result { + fn from_str(src: &str) -> Result { Ok(match src.to_lowercase().as_str() { "foo" => EnumNoFields::Foo, "bar" => EnumNoFields::Bar, diff --git a/impl/doc/try_into.md b/impl/doc/try_into.md index 3953fbf7..98edc1d7 100644 --- a/impl/doc/try_into.md +++ b/impl/doc/try_into.md @@ -97,7 +97,7 @@ Code like this will be generated: # } impl derive_more::TryFrom for (i32) { type Error = &'static str; - fn try_from(value: MixedInts) -> Result { + fn try_from(value: MixedInts) -> Result { match value { MixedInts::SmallInt(__0) => Ok(__0), _ => Err("Only SmallInt can be converted to i32"), @@ -106,7 +106,7 @@ impl derive_more::TryFrom for (i32) { } impl derive_more::TryFrom for (i64) { type Error = &'static str; - fn try_from(value: MixedInts) -> Result { + fn try_from(value: MixedInts) -> Result { match value { MixedInts::BigInt(__0) => Ok(__0), _ => Err("Only BigInt can be converted to i64"), @@ -115,7 +115,7 @@ impl derive_more::TryFrom for (i64) { } impl derive_more::TryFrom for (i32, i32) { type Error = &'static str; - fn try_from(value: MixedInts) -> Result { + fn try_from(value: MixedInts) -> Result { match value { MixedInts::TwoSmallInts(__0, __1) => Ok((__0, __1)), _ => Err("Only TwoSmallInts can be converted to (i32, i32)"), @@ -124,7 +124,7 @@ impl derive_more::TryFrom for (i32, i32) { } impl derive_more::TryFrom for (i64, i64) { type Error = &'static str; - fn try_from(value: MixedInts) -> Result { + fn try_from(value: MixedInts) -> Result { match value { MixedInts::NamedSmallInts { x: __0, y: __1 } => Ok((__0, __1)), _ => Err("Only NamedSmallInts can be converted to (i64, i64)"), @@ -133,7 +133,7 @@ impl derive_more::TryFrom for (i64, i64) { } impl derive_more::TryFrom for (u32) { type Error = &'static str; - fn try_from(value: MixedInts) -> Result { + fn try_from(value: MixedInts) -> Result { match value { MixedInts::UnsignedOne(__0) | MixedInts::UnsignedTwo(__0) => Ok(__0), _ => Err("Only UnsignedOne, UnsignedTwo can be converted to u32"), @@ -163,7 +163,7 @@ Code like this will be generated: # } impl derive_more::TryFrom for (i32) { type Error = &'static str; - fn try_from(value: EnumWithUnit) -> Result { + fn try_from(value: EnumWithUnit) -> Result { match value { EnumWithUnit::SmallInt(__0) => Ok(__0), _ => Err("Only SmallInt can be converted to i32"), @@ -172,7 +172,7 @@ impl derive_more::TryFrom for (i32) { } impl derive_more::TryFrom for () { type Error = &'static str; - fn try_from(value: EnumWithUnit) -> Result { + fn try_from(value: EnumWithUnit) -> Result { match value { EnumWithUnit::Unit => Ok(()), _ => Err("Only Unit can be converted to ()"), diff --git a/impl/src/from_str.rs b/impl/src/from_str.rs index 16ccbffb..5d502eb5 100644 --- a/impl/src/from_str.rs +++ b/impl/src/from_str.rs @@ -35,14 +35,15 @@ pub fn struct_from(state: &State, trait_name: &'static str) -> TokenStream { let initializers = [quote! { #casted_trait::from_str(src)? }]; let body = single_field_data.initializer(&initializers); + let error = quote! { <#field_type as #trait_path>::Err }; quote! { #[automatically_derived] impl #impl_generics #trait_path for #input_type #ty_generics #where_clause { - type Err = <#field_type as #trait_path>::Err; + type Err = #error; #[inline] - fn from_str(src: &str) -> derive_more::core::result::Result { + fn from_str(src: &str) -> derive_more::core::result::Result { derive_more::core::result::Result::Ok(#body) } } @@ -97,7 +98,7 @@ fn enum_from( type Err = derive_more::FromStrError; #[inline] - fn from_str(src: &str) -> derive_more::core::result::Result { + fn from_str(src: &str) -> derive_more::core::result::Result { Ok(match src.to_lowercase().as_str() { #(#cases)* _ => return Err(derive_more::FromStrError::new(#input_type_name)), diff --git a/impl/src/try_from.rs b/impl/src/try_from.rs index f50c321f..fef79d43 100644 --- a/impl/src/try_from.rs +++ b/impl/src/try_from.rs @@ -119,14 +119,16 @@ impl ToTokens for Expansion { ) .unzip(); + let error = quote! { derive_more::TryFromReprError<#repr_ty> }; + quote! { #[automatically_derived] impl #impl_generics derive_more::TryFrom<#repr_ty #ty_generics> for #ident #where_clause { - type Error = derive_more::TryFromReprError<#repr_ty>; + type Error = #error; #[allow(non_upper_case_globals)] #[inline] - fn try_from(val: #repr_ty) -> derive_more::core::result::Result { + fn try_from(val: #repr_ty) -> derive_more::core::result::Result { #( const #consts: #repr_ty = #discriminants; )* match val { #(#consts => derive_more::core::result::Result::Ok(#ident::#variants),)* diff --git a/impl/src/try_into.rs b/impl/src/try_into.rs index a2ebce8b..70a4c620 100644 --- a/impl/src/try_into.rs +++ b/impl/src/try_into.rs @@ -99,17 +99,21 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result + }; + let try_from = quote! { #[automatically_derived] impl #impl_generics derive_more::core::convert::TryFrom< #reference_with_lifetime #input_type #ty_generics > for (#(#reference_with_lifetime #original_types),*) #where_clause { - type Error = derive_more::TryIntoError<#reference_with_lifetime #input_type #ty_generics>; + type Error = #error; #[inline] fn try_from( value: #reference_with_lifetime #input_type #ty_generics, - ) -> derive_more::core::result::Result { + ) -> derive_more::core::result::Result { match value { #(#matchers)|* => derive_more::core::result::Result::Ok(#vars), _ => derive_more::core::result::Result::Err(