diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b2db574..37cd0545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ([#454](https://github.com/JelteF/derive_more/pull/454)) - Silent no-op when `#[try_from(repr)]` attribute is not specified for `TryFrom` derive. ([#458](https://github.com/JelteF/derive_more/pull/458)) +- Missing trait bounds in `AsRef`/`AsMut` derives when associative types are involved. + ([#474](https://github.com/JelteF/derive_more/pull/474)) ## 2.0.1 - 2025-02-03 diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 21d653ab..53a417c6 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -101,4 +101,4 @@ full = [ "unwrap", ] -testing-helpers = ["dep:rustc_version"] +testing-helpers = ["syn/full", "dep:rustc_version"] diff --git a/impl/src/as/mod.rs b/impl/src/as/mod.rs index 72bbb83e..5e5ed68d 100644 --- a/impl/src/as/mod.rs +++ b/impl/src/as/mod.rs @@ -189,15 +189,7 @@ impl ToTokens for Expansion<'_> { let field_ref = quote! { & #mut_ self.#field_ident }; - let generics_search = GenericsSearch { - types: self.generics.type_params().map(|p| &p.ident).collect(), - lifetimes: self - .generics - .lifetimes() - .map(|p| &p.lifetime.ident) - .collect(), - consts: self.generics.const_params().map(|p| &p.ident).collect(), - }; + let generics_search = GenericsSearch::from(self.generics); let field_contains_generics = generics_search.any_in(field_ty); let is_blanket = diff --git a/impl/src/utils.rs b/impl/src/utils.rs index d178c33d..825d95d3 100644 --- a/impl/src/utils.rs +++ b/impl/src/utils.rs @@ -2400,6 +2400,16 @@ mod generics_search { pub(crate) consts: HashSet<&'s syn::Ident>, } + impl<'s> From<&'s syn::Generics> for GenericsSearch<'s> { + fn from(value: &'s syn::Generics) -> Self { + Self { + types: value.type_params().map(|p| &p.ident).collect(), + lifetimes: value.lifetimes().map(|p| &p.lifetime.ident).collect(), + consts: value.const_params().map(|p| &p.ident).collect(), + } + } + } + impl GenericsSearch<'_> { /// Checks the provided [`syn::Type`] to contain anything from this [`GenericsSearch`]. pub(crate) fn any_in(&self, ty: &syn::Type) -> bool { @@ -2422,27 +2432,139 @@ mod generics_search { } impl<'ast> Visit<'ast> for Visitor<'_> { + fn visit_expr_path(&mut self, ep: &'ast syn::ExprPath) { + self.found |= ep + .path + .get_ident() + .is_some_and(|ident| self.search.consts.contains(ident)); + + if !self.found { + syn::visit::visit_expr_path(self, ep); + } + } + + fn visit_lifetime(&mut self, lf: &'ast syn::Lifetime) { + self.found |= self.search.lifetimes.contains(&lf.ident); + + if !self.found { + syn::visit::visit_lifetime(self, lf); + } + } + fn visit_type_path(&mut self, tp: &'ast syn::TypePath) { self.found |= tp.path.get_ident().is_some_and(|ident| { self.search.types.contains(ident) || self.search.consts.contains(ident) }); - syn::visit::visit_type_path(self, tp) - } + if !self.found { + // `TypeParam::AssocType` case. + self.found |= tp.path.segments.first().is_some_and(|segment| { + matches!(segment.arguments, syn::PathArguments::None) + && self.search.types.contains(&segment.ident) + }); + } - fn visit_lifetime(&mut self, lf: &'ast syn::Lifetime) { - self.found |= self.search.lifetimes.contains(&lf.ident); + if !self.found { + syn::visit::visit_type_path(self, tp) + } + } + } - syn::visit::visit_lifetime(self, lf) + #[cfg(test)] + mod spec { + use quote::ToTokens as _; + use syn::parse_quote; + + use super::GenericsSearch; + + #[test] + fn types() { + let generics: syn::Generics = parse_quote! { }; + let search = GenericsSearch::from(&generics); + + for input in [ + parse_quote! { T }, + parse_quote! { &T }, + parse_quote! { &'a T }, + parse_quote! { &&'a T }, + parse_quote! { Type<'a, T> }, + parse_quote! { path::Type }, + parse_quote! { path::<'a, T>::Type }, + parse_quote! { >::Type }, + parse_quote! { ::Type }, + parse_quote! { T::Type }, + parse_quote! { ::Type }, + parse_quote! { [T] }, + parse_quote! { [T; 3] }, + parse_quote! { [T; _] }, + parse_quote! { (T) }, + parse_quote! { (T,) }, + parse_quote! { (T, u8) }, + parse_quote! { (u8, T) }, + parse_quote! { fn(T) }, + parse_quote! { fn(u8, T) }, + parse_quote! { fn(_) -> T }, + parse_quote! { fn(_) -> (u8, T) }, + ] { + assert!( + search.any_in(&input), + "cannot find type parameter `T` in type `{}`", + input.into_token_stream(), + ); + } } - fn visit_expr_path(&mut self, ep: &'ast syn::ExprPath) { - self.found |= ep - .path - .get_ident() - .is_some_and(|ident| self.search.consts.contains(ident)); + #[test] + fn lifetimes() { + let generics: syn::Generics = parse_quote! { <'a> }; + let search = GenericsSearch::from(&generics); + + for input in [ + parse_quote! { &'a T }, + parse_quote! { &&'a T }, + parse_quote! { Type<'a> }, + parse_quote! { path::Type<'a> }, + parse_quote! { path::<'a>::Type }, + parse_quote! { >::Type }, + parse_quote! { ::Type<'a> }, + ] { + assert!( + search.any_in(&input), + "cannot find lifetime parameter `'a` in type `{}`", + input.into_token_stream(), + ); + } + } - syn::visit::visit_expr_path(self, ep) + #[test] + fn consts() { + let generics: syn::Generics = parse_quote! { }; + let search = GenericsSearch::from(&generics); + + for input in [ + parse_quote! { [_; N] }, + parse_quote! { Type }, + #[cfg(feature = "testing-helpers")] // requires `syn/full` + parse_quote! { Type<{ N }> }, + parse_quote! { path::Type }, + #[cfg(feature = "testing-helpers")] // requires `syn/full` + parse_quote! { path::Type<{ N }> }, + parse_quote! { path::::Type }, + #[cfg(feature = "testing-helpers")] // requires `syn/full` + parse_quote! { path::<{ N }>::Type }, + parse_quote! { >::Type }, + #[cfg(feature = "testing-helpers")] // requires `syn/full` + parse_quote! { >::Type }, + parse_quote! { ::Type }, + #[cfg(feature = "testing-helpers")] // requires `syn/full` + parse_quote! { ::Type<{ N }> }, + ] { + assert!( + search.any_in(&input), + "cannot find const parameter `N` in type `{}`", + input.into_token_stream(), + ); + } } } } diff --git a/tests/as_mut.rs b/tests/as_mut.rs index 5bb5c4d1..ebfb6331 100644 --- a/tests/as_mut.rs +++ b/tests/as_mut.rs @@ -58,78 +58,98 @@ impl AsMut<[i32]> for ConstParamHelper<0> { } } +trait Some { + type Assoc; +} + +impl Some for () { + type Assoc = Helper; +} + +impl Some for bool { + type Assoc = String; +} + +impl Some for u8 { + type Assoc = i32; +} + +impl Some for str { + type Assoc = u8; +} + mod single_field { use super::*; mod tuple { use super::*; - #[derive(AsMut)] - struct Nothing(String); - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing(String); + let mut item = Nothing("test".to_owned()); assert!(ptr::eq(item.as_mut(), &mut item.0)); } - #[derive(AsMut)] - #[as_mut(forward)] - struct Forward(String); - #[test] fn forward() { + #[derive(AsMut)] + #[as_mut(forward)] + struct Forward(String); + let mut item = Forward("test".to_owned()); let rf: &mut str = item.as_mut(); assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - struct Field(#[as_mut] String); - #[test] fn field() { + #[derive(AsMut)] + struct Field(#[as_mut] String); + let mut item = Field("test".to_owned()); assert!(ptr::eq(item.as_mut(), &mut item.0)); } - #[derive(AsMut)] - struct FieldForward(#[as_mut(forward)] String); - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward(#[as_mut(forward)] String); + let mut item = FieldForward("test".to_owned()); let rf: &mut str = item.as_mut(); assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - #[as_mut(i32, f64)] - struct Types(Helper); + #[test] + fn types() { + #[derive(AsMut)] + #[as_mut(i32, f64)] + struct Types(Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for Types { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for Types { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } } - } - // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsMut for Types { - fn as_mut(&mut self) -> &mut Helper { - &mut self.0 + // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsMut for Types { + fn as_mut(&mut self) -> &mut Helper { + &mut self.0 + } } - } - #[test] - fn types() { let mut item = Types(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -139,21 +159,21 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - #[as_mut(i32, Helper)] - struct TypesWithInner(Helper); + #[test] + fn types_with_inner() { + #[derive(AsMut)] + #[as_mut(i32, Helper)] + struct TypesWithInner(Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for TypesWithInner { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for TypesWithInner { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } } - } - #[test] - fn types_with_inner() { let mut item = TypesWithInner(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -163,23 +183,23 @@ mod single_field { assert!(ptr::eq(rf, &mut item.0)); } - type RenamedFoo = Helper; + #[test] + fn types_with_renamed_inner() { + type RenamedFoo = Helper; - #[derive(AsMut)] - #[as_mut(i32, RenamedFoo)] - struct TypesWithRenamedInner(Helper); + #[derive(AsMut)] + #[as_mut(i32, RenamedFoo)] + struct TypesWithRenamedInner(Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for TypesWithRenamedInner { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for TypesWithRenamedInner { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } } - } - #[test] - fn types_with_renamed_inner() { let mut item = TypesWithRenamedInner(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -189,28 +209,28 @@ mod single_field { assert!(ptr::eq(rf, &mut item.0)); } - #[derive(AsMut)] - struct FieldTypes(#[as_mut(i32, f64)] Helper); + #[test] + fn field_types() { + #[derive(AsMut)] + struct FieldTypes(#[as_mut(i32, f64)] Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for FieldTypes { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for FieldTypes { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } } - } - // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsMut for FieldTypes { - fn as_mut(&mut self) -> &mut Helper { - &mut self.0 + // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsMut for FieldTypes { + fn as_mut(&mut self) -> &mut Helper { + &mut self.0 + } } - } - #[test] - fn field_types() { let mut item = FieldTypes(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -220,20 +240,20 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - struct FieldTypesWithInner(#[as_mut(i32, Helper)] Helper); + #[test] + fn field_types_with_inner() { + #[derive(AsMut)] + struct FieldTypesWithInner(#[as_mut(i32, Helper)] Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for FieldTypesWithInner { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for FieldTypesWithInner { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } } - } - #[test] - fn field_types_with_inner() { let mut item = FieldTypesWithInner(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -243,20 +263,22 @@ mod single_field { assert!(ptr::eq(rf, &mut item.0)); } - #[derive(AsMut)] - struct FieldTypesWithRenamedInner(#[as_mut(i32, RenamedFoo)] Helper); + #[test] + fn field_types_with_renamed_inner() { + type RenamedFoo = Helper; + + #[derive(AsMut)] + struct FieldTypesWithRenamedInner(#[as_mut(i32, RenamedFoo)] Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for FieldTypesWithRenamedInner { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to + // the field type, by producing a trait implementations conflict error during compilation, + // if it does. + impl AsMut for FieldTypesWithRenamedInner { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } } - } - #[test] - fn field_types_with_renamed_inner() { let mut item = FieldTypesWithRenamedInner(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -269,64 +291,97 @@ mod single_field { mod generic { use super::*; - #[derive(AsMut)] - struct Nothing(T); - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing(T); + let mut item = Nothing("test".to_owned()); assert!(ptr::eq(item.as_mut(), &mut item.0)); } - #[derive(AsMut)] - #[as_mut(forward)] - struct Forward(T); + #[test] + fn nothing_assoc() { + #[derive(AsMut)] + struct Nothing(T::Assoc); + + let mut item = Nothing::("test".to_owned()); + + assert!(ptr::eq(item.as_mut(), &mut item.0)); + } #[test] fn forward() { + #[derive(AsMut)] + #[as_mut(forward)] + struct Forward(T); + let mut item = Forward("test".to_owned()); let rf: &mut str = item.as_mut(); assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - struct Field(#[as_mut] T); + #[test] + fn forward_assoc() { + #[derive(AsMut)] + #[as_mut(forward)] + struct Forward(T::Assoc); + + let mut item = Forward::("test".to_owned()); + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + } #[test] fn field() { + #[derive(AsMut)] + struct Field(#[as_mut] T); + let mut item = Field("test".to_owned()); assert!(ptr::eq(item.as_mut(), &mut item.0)); } - #[derive(AsMut)] - struct FieldForward(#[as_mut(forward)] T); - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward(#[as_mut(forward)] T); + let mut item = FieldForward("test".to_owned()); let rf: &mut str = item.as_mut(); assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - #[as_mut(i32, f64)] - struct Types(T); + #[test] + fn field_forward_assoc() { + #[derive(AsMut)] + struct FieldForward(#[as_mut(forward)] T::Assoc); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsMut for Types { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() - } + let mut item = FieldForward::("test".to_owned()); + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); } #[test] fn types() { + #[derive(AsMut)] + #[as_mut(i32, f64)] + struct Types(T); + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsMut for Types { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } + } + let mut item = Types(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -336,31 +391,69 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - #[as_mut(Vec)] - struct TypesInner(Vec); + #[test] + fn types_assoc() { + #[derive(AsMut)] + #[as_mut(i32, f64)] + struct Types(T::Assoc); + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsMut for Types + where + T::Assoc: AsMut, + { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } + } + + let mut item = Types::<()>(Helper(1, 2.0, false)); + + let rf: &mut i32 = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + + let rf: &mut f64 = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + } #[test] fn types_inner() { + #[derive(AsMut)] + #[as_mut(Vec)] + struct TypesInner(Vec); + let mut item = TypesInner(vec![1i32]); assert!(ptr::eq(item.as_mut(), &mut item.0)); } - #[derive(AsMut)] - struct FieldTypes(#[as_mut(i32, f64)] T); + #[test] + fn types_inner_assoc() { + #[derive(AsMut)] + #[as_mut(Vec)] + struct TypesInner(Vec); - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsMut for FieldTypes { - fn as_mut(&mut self) -> &mut bool { - self.0.as_mut() - } + let mut item = TypesInner::(vec![1i32]); + + assert!(ptr::eq(item.as_mut(), &mut item.0)); } #[test] fn field_types() { + #[derive(AsMut)] + struct FieldTypes(#[as_mut(i32, f64)] T); + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl> AsMut for FieldTypes { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } + } + let mut item = FieldTypes(Helper(1, 2.0, false)); let rf: &mut i32 = item.as_mut(); @@ -370,55 +463,93 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - struct FieldTypesInner(#[as_mut(Vec)] Vec); + #[test] + fn field_types_assoc() { + #[derive(AsMut)] + struct FieldTypes(#[as_mut(i32, f64)] T::Assoc); + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for FieldTypes + where + T::Assoc: AsMut, + { + fn as_mut(&mut self) -> &mut bool { + self.0.as_mut() + } + } + + let mut item = FieldTypes::<()>(Helper(1, 2.0, false)); + + let rf: &mut i32 = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + + let rf: &mut f64 = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + } #[test] fn field_types_inner() { + #[derive(AsMut)] + struct FieldTypesInner(#[as_mut(Vec)] Vec); + let mut item = FieldTypesInner(vec![1i32]); assert!(ptr::eq(item.as_mut(), &mut item.0)); } - #[derive(AsMut)] - #[as_mut(i32)] - struct Lifetime<'a>(LifetimeHelper<'a>); + #[test] + fn field_types_inner_assoc() { + #[derive(AsMut)] + struct FieldTypesInner( + #[as_mut(Vec<::Assoc>)] Vec<::Assoc>, + ); + + let mut item = FieldTypesInner::(vec![1i32]); + + assert!(ptr::eq(item.as_mut(), &mut item.0)); + } #[test] fn lifetime() { + #[derive(AsMut)] + #[as_mut(i32)] + struct Lifetime<'a>(LifetimeHelper<'a>); + let mut item = Lifetime(LifetimeHelper::new(0)); assert!(ptr::eq(item.as_mut(), item.0.as_mut())); } - #[derive(AsMut)] - struct FieldLifetime<'a>(#[as_mut(i32)] LifetimeHelper<'a>); - #[test] fn field_lifetime() { + #[derive(AsMut)] + struct FieldLifetime<'a>(#[as_mut(i32)] LifetimeHelper<'a>); + let mut item = FieldLifetime(LifetimeHelper::new(0)); assert!(ptr::eq(item.as_mut(), item.0.as_mut())); } - #[derive(AsMut)] - #[as_mut([i32])] - struct ConstParam(ConstParamHelper); - #[test] fn const_param() { + #[derive(AsMut)] + #[as_mut([i32])] + struct ConstParam(ConstParamHelper); + let mut item = ConstParam(ConstParamHelper([])); assert!(ptr::eq(item.as_mut(), item.0.as_mut())); } - #[derive(AsMut)] - struct FieldConstParam( - #[as_mut([i32])] ConstParamHelper, - ); - #[test] fn field_const_param() { + #[derive(AsMut)] + struct FieldConstParam( + #[as_mut([i32])] ConstParamHelper, + ); + let mut item = FieldConstParam(ConstParamHelper([])); assert!(ptr::eq(item.as_mut(), item.0.as_mut())); @@ -445,13 +576,13 @@ mod single_field { mod named { use super::*; - #[derive(AsMut)] - struct Nothing { - first: String, - } - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing { + first: String, + } + let mut item = Nothing { first: "test".to_owned(), }; @@ -459,14 +590,14 @@ mod single_field { assert!(ptr::eq(item.as_mut(), &mut item.first)); } - #[derive(AsMut)] - #[as_mut(forward)] - struct Forward { - first: String, - } - #[test] fn forward() { + #[derive(AsMut)] + #[as_mut(forward)] + struct Forward { + first: String, + } + let mut item = Forward { first: "test".to_owned(), }; @@ -475,14 +606,14 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - struct Field { - #[as_mut] - first: String, - } - #[test] fn field() { + #[derive(AsMut)] + struct Field { + #[as_mut] + first: String, + } + let mut item = Field { first: "test".to_owned(), }; @@ -490,14 +621,14 @@ mod single_field { assert!(ptr::eq(item.as_mut(), &mut item.first)); } - #[derive(AsMut)] - struct FieldForward { - #[as_mut(forward)] - first: String, - } - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward { + #[as_mut(forward)] + first: String, + } + let mut item = FieldForward { first: "test".to_owned(), }; @@ -506,31 +637,31 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - #[as_mut(i32, f64)] - struct Types { - first: Helper, - } + #[test] + fn types() { + #[derive(AsMut)] + #[as_mut(i32, f64)] + struct Types { + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for Types { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for Types { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsMut for Types { - fn as_mut(&mut self) -> &mut Helper { - &mut self.first + // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsMut for Types { + fn as_mut(&mut self) -> &mut Helper { + &mut self.first + } } - } - #[test] - fn types() { let mut item = Types { first: Helper(1, 2.0, false), }; @@ -542,23 +673,23 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - #[as_mut(i32, Helper)] - struct TypesWithInner { - first: Helper, - } + #[test] + fn types_with_inner() { + #[derive(AsMut)] + #[as_mut(i32, Helper)] + struct TypesWithInner { + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for TypesWithInner { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for TypesWithInner { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - #[test] - fn types_with_inner() { let mut item = TypesWithInner { first: Helper(1, 2.0, false), }; @@ -570,25 +701,25 @@ mod single_field { assert!(ptr::eq(rf, &mut item.first)); } - type RenamedFoo = Helper; + #[test] + fn types_with_renamed_inner() { + type RenamedFoo = Helper; - #[derive(AsMut)] - #[as_mut(i32, RenamedFoo)] - struct TypesWithRenamedInner { - first: Helper, - } + #[derive(AsMut)] + #[as_mut(i32, RenamedFoo)] + struct TypesWithRenamedInner { + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for TypesWithRenamedInner { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for TypesWithRenamedInner { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - #[test] - fn types_with_renamed_inner() { let mut item = TypesWithRenamedInner { first: Helper(1, 2.0, false), }; @@ -600,31 +731,31 @@ mod single_field { assert!(ptr::eq(rf, &mut item.first)); } - #[derive(AsMut)] - struct FieldTypes { - #[as_mut(i32, f64)] - first: Helper, - } + #[test] + fn field_types() { + #[derive(AsMut)] + struct FieldTypes { + #[as_mut(i32, f64)] + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for FieldTypes { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for FieldTypes { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsMut for FieldTypes { - fn as_mut(&mut self) -> &mut Helper { - &mut self.first + // Asserts that the macro expansion doesn't generate an `AsMut` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsMut for FieldTypes { + fn as_mut(&mut self) -> &mut Helper { + &mut self.first + } } - } - #[test] - fn field_types() { let mut item = FieldTypes { first: Helper(1, 2.0, false), }; @@ -636,23 +767,23 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - struct FieldTypesWithInner { - #[as_mut(i32, Helper)] - first: Helper, - } + #[test] + fn field_types_with_inner() { + #[derive(AsMut)] + struct FieldTypesWithInner { + #[as_mut(i32, Helper)] + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for FieldTypesWithInner { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for FieldTypesWithInner { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - #[test] - fn field_types_with_inner() { let mut item = FieldTypesWithInner { first: Helper(1, 2.0, false), }; @@ -664,23 +795,25 @@ mod single_field { assert!(ptr::eq(rf, &mut item.first)); } - #[derive(AsMut)] - struct FieldTypesWithRenamedInner { - #[as_mut(i32, RenamedFoo)] - first: Helper, - } + #[test] + fn field_types_with_renamed_inner() { + type RenamedFoo = Helper; + + #[derive(AsMut)] + struct FieldTypesWithRenamedInner { + #[as_mut(i32, RenamedFoo)] + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsMut for FieldTypesWithRenamedInner { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsMut for FieldTypesWithRenamedInner { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - #[test] - fn field_types_with_renamed_inner() { let mut item = FieldTypesWithRenamedInner { first: Helper(1, 2.0, false), }; @@ -695,13 +828,13 @@ mod single_field { mod generic { use super::*; - #[derive(AsMut)] - struct Nothing { - first: T, - } - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing { + first: T, + } + let mut item = Nothing { first: "test".to_owned(), }; @@ -709,14 +842,28 @@ mod single_field { assert!(ptr::eq(item.as_mut(), &mut item.first)); } - #[derive(AsMut)] - #[as_mut(forward)] - struct Forward { - first: T, + #[test] + fn nothing_assoc() { + #[derive(AsMut)] + struct Nothing { + first: ::Assoc, + } + + let mut item = Nothing:: { + first: "test".to_owned(), + }; + + assert!(ptr::eq(item.as_mut(), &mut item.first)); } #[test] fn struct_forward() { + #[derive(AsMut)] + #[as_mut(forward)] + struct Forward { + first: T, + } + let mut item = Forward { first: "test".to_owned(), }; @@ -725,14 +872,30 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - struct Field { - #[as_mut] - first: T, + #[test] + fn struct_forward_assoc() { + #[derive(AsMut)] + #[as_mut(forward)] + struct Forward { + first: T::Assoc, + } + + let mut item = Forward:: { + first: "test".to_owned(), + }; + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); } #[test] fn field() { + #[derive(AsMut)] + struct Field { + #[as_mut] + first: T, + } + let mut item = Field { first: "test".to_owned(), }; @@ -740,14 +903,14 @@ mod single_field { assert!(ptr::eq(item.as_mut(), &mut item.first)); } - #[derive(AsMut)] - struct FieldForward { - #[as_mut(forward)] - first: T, - } - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward { + #[as_mut(forward)] + first: T, + } + let mut item = FieldForward { first: "test".to_owned(), }; @@ -756,23 +919,39 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - #[as_mut(i32, f64)] - struct Types { - first: T, - } - - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsMut for Types { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + #[test] + fn field_forward_assoc() { + #[derive(AsMut)] + struct FieldForward { + #[as_mut(forward)] + first: T::Assoc, } + + let mut item = FieldForward:: { + first: "test".to_owned(), + }; + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); } #[test] fn types() { + #[derive(AsMut)] + #[as_mut(i32, f64)] + struct Types { + first: T, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsMut for Types { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } + } + let mut item = Types { first: Helper(1, 2.0, false), }; @@ -784,36 +963,80 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - #[as_mut(Vec)] - struct TypesInner { - first: Vec, + #[test] + fn types_assoc() { + #[derive(AsMut)] + #[as_mut(i32, f64)] + struct Types { + first: T::Assoc, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsMut for Types + where + T::Assoc: AsMut, + { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } + } + + let mut item = Types::<()> { + first: Helper(1, 2.0, false), + }; + + let rf: &mut i32 = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); + + let rf: &mut f64 = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); } #[test] fn types_inner() { + #[derive(AsMut)] + #[as_mut(Vec)] + struct TypesInner { + first: Vec, + } + let mut item = TypesInner { first: vec![1i32] }; assert!(ptr::eq(item.as_mut(), &mut item.first)); } - #[derive(AsMut)] - struct FieldTypes { - #[as_mut(i32, f64)] - first: T, + #[test] + fn types_inner_assoc() { + #[derive(AsMut)] + #[as_mut(Vec)] + struct TypesInner { + first: Vec, + } + + let mut item = TypesInner:: { first: vec![1i32] }; + + assert!(ptr::eq(item.as_mut(), &mut item.first)); } - // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsMut for FieldTypes { - fn as_mut(&mut self) -> &mut bool { - self.first.as_mut() + #[test] + fn field_types() { + #[derive(AsMut)] + struct FieldTypes { + #[as_mut(i32, f64)] + first: T, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsMut for FieldTypes { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } } - } - #[test] - fn field_types() { let mut item = FieldTypes { first: Helper(1, 2.0, false), }; @@ -825,27 +1048,71 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - struct FieldTypesInner { - #[as_mut(Vec)] - first: Vec, + #[test] + fn field_types_assoc() { + #[derive(AsMut)] + struct FieldTypes { + #[as_mut(i32, f64)] + first: T::Assoc, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsMut` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsMut for FieldTypes + where + T::Assoc: AsMut, + { + fn as_mut(&mut self) -> &mut bool { + self.first.as_mut() + } + } + + let mut item = FieldTypes::<()> { + first: Helper(1, 2.0, false), + }; + + let rf: &mut i32 = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); + + let rf: &mut f64 = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); } #[test] fn field_types_inner() { + #[derive(AsMut)] + struct FieldTypesInner { + #[as_mut(Vec)] + first: Vec, + } + let mut item = FieldTypesInner { first: vec![1i32] }; assert!(ptr::eq(item.as_mut(), &mut item.first)); } - #[derive(AsMut)] - #[as_mut(i32)] - struct Lifetime<'a> { - first: LifetimeHelper<'a>, + #[test] + fn field_types_inner_assoc() { + #[derive(AsMut)] + struct FieldTypesInner { + #[as_mut(Vec<::Assoc>)] + first: Vec<::Assoc>, + } + + let mut item = FieldTypesInner:: { first: vec![1i32] }; + + assert!(ptr::eq(item.as_mut(), &mut item.first)); } #[test] fn lifetime() { + #[derive(AsMut)] + #[as_mut(i32)] + struct Lifetime<'a> { + first: LifetimeHelper<'a>, + } + let mut item = Lifetime { first: LifetimeHelper::new(0), }; @@ -853,14 +1120,14 @@ mod single_field { assert!(ptr::eq(item.as_mut(), item.first.as_mut())); } - #[derive(AsMut)] - struct FieldLifetime<'a> { - #[as_mut(i32)] - first: LifetimeHelper<'a>, - } - #[test] fn field_lifetime() { + #[derive(AsMut)] + struct FieldLifetime<'a> { + #[as_mut(i32)] + first: LifetimeHelper<'a>, + } + let mut item = FieldLifetime { first: LifetimeHelper::new(0), }; @@ -868,14 +1135,14 @@ mod single_field { assert!(ptr::eq(item.as_mut(), item.first.as_mut())); } - #[derive(AsMut)] - #[as_mut([i32])] - struct ConstParam { - first: ConstParamHelper, - } - #[test] fn const_param() { + #[derive(AsMut)] + #[as_mut([i32])] + struct ConstParam { + first: ConstParamHelper, + } + let mut item = ConstParam { first: ConstParamHelper([]), }; @@ -883,14 +1150,14 @@ mod single_field { assert!(ptr::eq(item.as_mut(), item.first.as_mut())); } - #[derive(AsMut)] - struct FieldConstParam { - #[as_mut([i32])] - first: ConstParamHelper, - } - #[test] fn field_const_param() { + #[derive(AsMut)] + struct FieldConstParam { + #[as_mut([i32])] + first: ConstParamHelper, + } + let mut item = FieldConstParam { first: ConstParamHelper([]), }; @@ -928,84 +1195,84 @@ mod multi_field { mod tuple { use super::*; - #[derive(AsMut)] - struct Nothing(String, i32); - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing(String, i32); + let mut item = Nothing("test".to_owned(), 0); assert!(ptr::eq(item.as_mut(), &mut item.0)); assert!(ptr::eq(item.as_mut(), &mut item.1)); } - #[derive(AsMut)] - struct Skip(String, i32, #[as_mut(skip)] f64); + #[test] + fn skip() { + #[derive(AsMut)] + struct Skip(String, i32, #[as_mut(skip)] f64); - // Asserts that the macro expansion doesn't generate `AsMut` impl for the skipped field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsMut for Skip { - fn as_mut(&mut self) -> &mut f64 { - &mut self.2 + // Asserts that the macro expansion doesn't generate `AsMut` impl for the skipped field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsMut for Skip { + fn as_mut(&mut self) -> &mut f64 { + &mut self.2 + } } - } - #[test] - fn skip() { let mut item = Skip("test".to_owned(), 0, 0.0); assert!(ptr::eq(item.as_mut(), &mut item.0)); assert!(ptr::eq(item.as_mut(), &mut item.1)); } - #[derive(AsMut)] - struct Field(#[as_mut] String, #[as_mut] i32, f64); + #[test] + fn field() { + #[derive(AsMut)] + struct Field(#[as_mut] String, #[as_mut] i32, f64); - // Asserts that the macro expansion doesn't generate `AsMut` impl for the third field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsMut for Field { - fn as_mut(&mut self) -> &mut f64 { - &mut self.2 + // Asserts that the macro expansion doesn't generate `AsMut` impl for the third field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsMut for Field { + fn as_mut(&mut self) -> &mut f64 { + &mut self.2 + } } - } - #[test] - fn field() { let mut item = Field("test".to_owned(), 0, 0.0); assert!(ptr::eq(item.as_mut(), &mut item.0)); assert!(ptr::eq(item.as_mut(), &mut item.1)); } - #[derive(AsMut)] - struct FieldForward(#[as_mut(forward)] String, i32); - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward(#[as_mut(forward)] String, i32); + let mut item = FieldForward("test".to_owned(), 0); let rf: &mut str = item.as_mut(); assert!(ptr::eq(rf, item.0.as_mut())); } - type RenamedString = String; + #[test] + fn types() { + type RenamedString = String; - #[derive(AsMut)] - struct Types( - #[as_mut(str, RenamedString)] String, - #[as_mut([u8])] Vec, - ); + #[derive(AsMut)] + struct Types( + #[as_mut(str, RenamedString)] String, + #[as_mut([u8])] Vec, + ); - // Asserts that the macro expansion doesn't generate `AsMut` impl for the field type, by - // producing trait implementations conflict error during compilation, if it does. - impl AsMut> for Types { - fn as_mut(&mut self) -> &mut Vec { - &mut self.1 + // Asserts that the macro expansion doesn't generate `AsMut` impl for the field type, by + // producing trait implementations conflict error during compilation, if it does. + impl AsMut> for Types { + fn as_mut(&mut self) -> &mut Vec { + &mut self.1 + } } - } - #[test] - fn types() { let mut item = Types("test".to_owned(), vec![0]); let rf: &mut str = item.as_mut(); @@ -1021,55 +1288,66 @@ mod multi_field { mod generic { use super::*; - #[derive(AsMut)] - struct Nothing(Vec, VecDeque); - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing(Vec, VecDeque); + let mut item = Nothing(vec![1], VecDeque::from([2])); assert!(ptr::eq(item.as_mut(), &mut item.0)); assert!(ptr::eq(item.as_mut(), &mut item.1)); } - #[derive(AsMut)] - struct Skip(Vec, VecDeque, #[as_mut(skip)] V); - #[test] fn skip() { + #[derive(AsMut)] + struct Skip(Vec, VecDeque, #[as_mut(skip)] V); + let mut item = Skip(vec![1], VecDeque::from([2]), 0); assert!(ptr::eq(item.as_mut(), &mut item.0)); assert!(ptr::eq(item.as_mut(), &mut item.1)); } - #[derive(AsMut)] - struct Field(#[as_mut] Vec, #[as_mut] VecDeque, V); - #[test] fn field() { + #[derive(AsMut)] + struct Field(#[as_mut] Vec, #[as_mut] VecDeque, V); + let mut item = Field(vec![1], VecDeque::from([2]), 0); assert!(ptr::eq(item.as_mut(), &mut item.0)); assert!(ptr::eq(item.as_mut(), &mut item.1)); } - #[derive(AsMut)] - struct FieldForward(#[as_mut(forward)] T, U); - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward(#[as_mut(forward)] T, U); + let mut item = FieldForward("test".to_owned(), 0); let rf: &mut str = item.as_mut(); assert!(ptr::eq(rf, item.0.as_mut())); } - #[derive(AsMut)] - struct Types(#[as_mut(str)] T, #[as_mut([u8])] U); + #[test] + fn field_forward_assoc() { + #[derive(AsMut)] + struct FieldForward(#[as_mut(forward)] T::Assoc, U); + + let mut item = FieldForward::("test".to_owned(), 0); + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + } #[test] fn types() { + #[derive(AsMut)] + struct Types(#[as_mut(str)] T, #[as_mut([u8])] U); + let mut item = Types("test".to_owned(), vec![0]); let rf: &mut str = item.as_mut(); @@ -1079,14 +1357,31 @@ mod multi_field { assert!(ptr::eq(rf, item.1.as_mut())); } - #[derive(AsMut)] - struct TypesWithInner( - #[as_mut(Vec, [T])] Vec, - #[as_mut(str)] U, - ); + #[test] + fn types_assoc() { + #[derive(AsMut)] + struct Types( + #[as_mut(str)] ::Assoc, + #[as_mut([u8])] Vec, + ); + + let mut item = Types::("test".to_owned(), vec![0]); + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + + let rf: &mut [u8] = item.as_mut(); + assert!(ptr::eq(rf, item.1.as_mut())); + } #[test] fn types_with_inner() { + #[derive(AsMut)] + struct TypesWithInner( + #[as_mut(Vec, [T])] Vec, + #[as_mut(str)] U, + ); + let mut item = TypesWithInner(vec![1i32], "a".to_owned()); let rf: &mut Vec = item.as_mut(); @@ -1099,15 +1394,45 @@ mod multi_field { assert!(ptr::eq(rf, item.1.as_mut())); } - #[derive(AsMut)] - struct FieldNonGeneric(#[as_mut([T])] Vec, T); + #[test] + fn types_with_inner_assoc() { + #[derive(AsMut)] + struct TypesWithInner( + #[as_mut(Vec, [T::Assoc])] Vec, + #[as_mut(str)] U::Assoc, + ); + + let mut item = TypesWithInner::(vec![1i32], "a".to_owned()); + + let rf: &mut Vec = item.as_mut(); + assert!(ptr::eq(rf, &mut item.0)); + + let rf: &mut [i32] = item.as_mut(); + assert!(ptr::eq(rf, item.0.as_mut())); + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.1.as_mut())); + } #[test] fn field_non_generic() { + #[derive(AsMut)] + struct FieldNonGeneric(#[as_mut([T])] Vec, T); + let mut item = FieldNonGeneric(vec![], 2i32); assert!(ptr::eq(item.as_mut(), item.0.as_mut())); } + + #[test] + fn field_non_generic_assoc() { + #[derive(AsMut)] + struct FieldNonGeneric(#[as_mut([T::Assoc])] Vec, T); + + let mut item = FieldNonGeneric::(vec![], 2u8); + + assert!(ptr::eq(item.as_mut(), item.0.as_mut())); + } } #[cfg(nightly)] @@ -1122,14 +1447,14 @@ mod multi_field { mod named { use super::*; - #[derive(AsMut)] - struct Nothing { - first: String, - second: i32, - } - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing { + first: String, + second: i32, + } + let mut item = Nothing { first: "test".to_owned(), second: 0, @@ -1139,24 +1464,24 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), &mut item.second)); } - #[derive(AsMut)] - struct Skip { - first: String, - second: i32, - #[as_mut(skip)] - third: f64, - } + #[test] + fn skip() { + #[derive(AsMut)] + struct Skip { + first: String, + second: i32, + #[as_mut(skip)] + third: f64, + } - // Asserts that the macro expansion doesn't generate `AsMut` impl for the skipped field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsMut for Skip { - fn as_mut(&mut self) -> &mut f64 { - &mut self.third + // Asserts that the macro expansion doesn't generate `AsMut` impl for the skipped field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsMut for Skip { + fn as_mut(&mut self) -> &mut f64 { + &mut self.third + } } - } - #[test] - fn skip() { let mut item = Skip { first: "test".to_owned(), second: 0, @@ -1167,25 +1492,25 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), &mut item.second)); } - #[derive(AsMut)] - struct Field { - #[as_mut] - first: String, - #[as_mut] - second: i32, - third: f64, - } + #[test] + fn field() { + #[derive(AsMut)] + struct Field { + #[as_mut] + first: String, + #[as_mut] + second: i32, + third: f64, + } - // Asserts that the macro expansion doesn't generate `AsMut` impl for the `third` field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsMut for Field { - fn as_mut(&mut self) -> &mut f64 { - &mut self.third + // Asserts that the macro expansion doesn't generate `AsMut` impl for the `third` field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsMut for Field { + fn as_mut(&mut self) -> &mut f64 { + &mut self.third + } } - } - #[test] - fn field() { let mut item = Field { first: "test".to_owned(), second: 0, @@ -1196,15 +1521,15 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), &mut item.second)); } - #[derive(AsMut)] - struct FieldForward { - #[as_mut(forward)] - first: String, - second: i32, - } - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward { + #[as_mut(forward)] + first: String, + second: i32, + } + let mut item = FieldForward { first: "test".to_owned(), second: 0, @@ -1214,26 +1539,26 @@ mod multi_field { assert!(ptr::eq(rf, item.first.as_mut())); } - type RenamedString = String; + #[test] + fn types() { + type RenamedString = String; - #[derive(AsMut)] - struct Types { - #[as_mut(str, RenamedString)] - first: String, - #[as_mut([u8])] - second: Vec, - } + #[derive(AsMut)] + struct Types { + #[as_mut(str, RenamedString)] + first: String, + #[as_mut([u8])] + second: Vec, + } - // Asserts that the macro expansion doesn't generate `AsMut` impl for unmentioned type, by - // producing trait implementations conflict error during compilation, if it does. - impl AsMut> for Types { - fn as_mut(&mut self) -> &mut Vec { - &mut self.second + // Asserts that the macro expansion doesn't generate `AsMut` impl for unmentioned type, + // by producing trait implementations conflict error during compilation, if it does. + impl AsMut> for Types { + fn as_mut(&mut self) -> &mut Vec { + &mut self.second + } } - } - #[test] - fn types() { let mut item = Types { first: "test".to_owned(), second: vec![0], @@ -1252,14 +1577,14 @@ mod multi_field { mod generic { use super::*; - #[derive(AsMut)] - struct Nothing { - first: Vec, - second: VecDeque, - } - #[test] fn nothing() { + #[derive(AsMut)] + struct Nothing { + first: Vec, + second: VecDeque, + } + let mut item = Nothing { first: vec![1], second: VecDeque::from([2]), @@ -1269,16 +1594,16 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), &mut item.second)); } - #[derive(AsMut)] - struct Skip { - first: Vec, - second: VecDeque, - #[as_mut(skip)] - third: V, - } - #[test] fn skip() { + #[derive(AsMut)] + struct Skip { + first: Vec, + second: VecDeque, + #[as_mut(skip)] + third: V, + } + let mut item = Skip { first: vec![1], second: VecDeque::from([2]), @@ -1289,17 +1614,17 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), &mut item.second)); } - #[derive(AsMut)] - struct Field { - #[as_mut] - first: Vec, - #[as_mut] - second: VecDeque, - third: V, - } - #[test] fn field() { + #[derive(AsMut)] + struct Field { + #[as_mut] + first: Vec, + #[as_mut] + second: VecDeque, + third: V, + } + let mut item = Field { first: vec![1], second: VecDeque::from([2]), @@ -1310,15 +1635,15 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), &mut item.second)); } - #[derive(AsMut)] - struct FieldForward { - #[as_mut(forward)] - first: T, - second: U, - } - #[test] fn field_forward() { + #[derive(AsMut)] + struct FieldForward { + #[as_mut(forward)] + first: T, + second: U, + } + let mut item = FieldForward { first: "test".to_owned(), second: 0, @@ -1328,16 +1653,34 @@ mod multi_field { assert!(ptr::eq(rf, item.first.as_mut())); } - #[derive(AsMut)] - struct Types { - #[as_mut(str)] - first: T, - #[as_mut([u8])] - second: U, + #[test] + fn field_forward_assoc() { + #[derive(AsMut)] + struct FieldForward { + #[as_mut(forward)] + first: T::Assoc, + second: U, + } + + let mut item = FieldForward:: { + first: "test".to_owned(), + second: 0, + }; + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); } #[test] fn types() { + #[derive(AsMut)] + struct Types { + #[as_mut(str)] + first: T, + #[as_mut([u8])] + second: U, + } + let mut item = Types { first: "test".to_owned(), second: vec![0], @@ -1350,16 +1693,38 @@ mod multi_field { assert!(ptr::eq(rf, item.second.as_mut())); } - #[derive(AsMut)] - struct TypesWithInner { - #[as_mut(Vec, [T])] - first: Vec, - #[as_mut(str)] - second: U, + #[test] + fn types_assoc() { + #[derive(AsMut)] + struct Types { + #[as_mut(str)] + first: T::Assoc, + #[as_mut([u8])] + second: Vec<::Assoc>, + } + + let mut item = Types:: { + first: "test".to_owned(), + second: vec![0], + }; + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); + + let rf: &mut [u8] = item.as_mut(); + assert!(ptr::eq(rf, item.second.as_mut())); } #[test] - fn types_inner() { + fn types_with_inner() { + #[derive(AsMut)] + struct TypesWithInner { + #[as_mut(Vec, [T])] + first: Vec, + #[as_mut(str)] + second: U, + } + let mut item = TypesWithInner { first: vec![1i32], second: "a".to_owned(), @@ -1375,15 +1740,40 @@ mod multi_field { assert!(ptr::eq(rf, item.second.as_mut())); } - #[derive(AsMut)] - struct FieldNonGeneric { - #[as_mut([T])] - first: Vec, - second: T, + #[test] + fn types_with_inner_assoc() { + #[derive(AsMut)] + struct TypesWithInner { + #[as_mut(Vec<::Assoc>, [::Assoc])] + first: Vec<::Assoc>, + #[as_mut(str)] + second: U::Assoc, + } + + let mut item = TypesWithInner:: { + first: vec![1i32], + second: "a".to_owned(), + }; + + let rf: &mut Vec = item.as_mut(); + assert!(ptr::eq(rf, &mut item.first)); + + let rf: &mut [i32] = item.as_mut(); + assert!(ptr::eq(rf, item.first.as_mut())); + + let rf: &mut str = item.as_mut(); + assert!(ptr::eq(rf, item.second.as_mut())); } #[test] fn field_non_generic() { + #[derive(AsMut)] + struct FieldNonGeneric { + #[as_mut([T])] + first: Vec, + second: T, + } + let mut item = FieldNonGeneric { first: vec![], second: 2i32, @@ -1391,6 +1781,23 @@ mod multi_field { assert!(ptr::eq(item.as_mut(), item.first.as_mut())); } + + #[test] + fn field_non_generic_assoc() { + #[derive(AsMut)] + struct FieldNonGeneric { + #[as_mut([::Assoc])] + first: Vec, + second: T, + } + + let mut item = FieldNonGeneric:: { + first: vec![], + second: 2u8, + }; + + assert!(ptr::eq(item.as_mut(), item.first.as_mut())); + } } #[cfg(nightly)] diff --git a/tests/as_ref.rs b/tests/as_ref.rs index cc58d4bc..39a35416 100644 --- a/tests/as_ref.rs +++ b/tests/as_ref.rs @@ -51,78 +51,98 @@ impl AsRef<[i32]> for ConstParamHelper<0> { } } +trait Some { + type Assoc; +} + +impl Some for () { + type Assoc = Helper; +} + +impl Some for bool { + type Assoc = String; +} + +impl Some for u8 { + type Assoc = i32; +} + +impl Some for str { + type Assoc = u8; +} + mod single_field { use super::*; mod tuple { use super::*; - #[derive(AsRef)] - struct Nothing(String); - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing(String); + let item = Nothing("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } - #[derive(AsRef)] - #[as_ref(forward)] - struct Forward(String); - #[test] fn forward() { + #[derive(AsRef)] + #[as_ref(forward)] + struct Forward(String); + let item = Forward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - struct Field(#[as_ref] String); - #[test] fn field() { + #[derive(AsRef)] + struct Field(#[as_ref] String); + let item = Field("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } - #[derive(AsRef)] - struct FieldForward(#[as_ref(forward)] String); - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward(#[as_ref(forward)] String); + let item = FieldForward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - #[as_ref(i32, f64)] - struct Types(Helper); + #[test] + fn types() { + #[derive(AsRef)] + #[as_ref(i32, f64)] + struct Types(Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for Types { - fn as_ref(&self) -> &bool { - self.0.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for Types { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } } - } - // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsRef for Types { - fn as_ref(&self) -> &Helper { - &self.0 + // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsRef for Types { + fn as_ref(&self) -> &Helper { + &self.0 + } } - } - #[test] - fn types() { let item = Types(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -132,21 +152,21 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - #[as_ref(i32, Helper)] - struct TypesWithInner(Helper); + #[test] + fn types_with_inner() { + #[derive(AsRef)] + #[as_ref(i32, Helper)] + struct TypesWithInner(Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for TypesWithInner { - fn as_ref(&self) -> &bool { - self.0.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for TypesWithInner { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } } - } - #[test] - fn types_with_inner() { let item = TypesWithInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -156,23 +176,23 @@ mod single_field { assert!(ptr::eq(rf, &item.0)); } - type RenamedFoo = Helper; + #[test] + fn types_with_renamed_inner() { + type RenamedFoo = Helper; - #[derive(AsRef)] - #[as_ref(i32, RenamedFoo)] - struct TypesWithRenamedInner(Helper); + #[derive(AsRef)] + #[as_ref(i32, RenamedFoo)] + struct TypesWithRenamedInner(Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for TypesWithRenamedInner { - fn as_ref(&self) -> &bool { - self.0.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for TypesWithRenamedInner { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } } - } - #[test] - fn types_with_renamed_inner() { let item = TypesWithRenamedInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -182,28 +202,28 @@ mod single_field { assert!(ptr::eq(rf, &item.0)); } - #[derive(AsRef)] - struct FieldTypes(#[as_ref(i32, f64)] Helper); + #[test] + fn field_types() { + #[derive(AsRef)] + struct FieldTypes(#[as_ref(i32, f64)] Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for FieldTypes { - fn as_ref(&self) -> &bool { - self.0.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for FieldTypes { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } } - } - // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsRef for FieldTypes { - fn as_ref(&self) -> &Helper { - &self.0 + // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsRef for FieldTypes { + fn as_ref(&self) -> &Helper { + &self.0 + } } - } - #[test] - fn field_types() { let item = FieldTypes(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -213,20 +233,20 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - struct FieldTypesWithInner(#[as_ref(i32, Helper)] Helper); + #[test] + fn field_types_with_inner() { + #[derive(AsRef)] + struct FieldTypesWithInner(#[as_ref(i32, Helper)] Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for FieldTypesWithInner { - fn as_ref(&self) -> &bool { - self.0.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for FieldTypesWithInner { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } } - } - #[test] - fn field_types_with_inner() { let item = FieldTypesWithInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -236,20 +256,22 @@ mod single_field { assert!(ptr::eq(rf, &item.0)); } - #[derive(AsRef)] - struct FieldTypesWithRenamedInner(#[as_ref(i32, RenamedFoo)] Helper); + #[test] + fn field_types_with_renamed_inner() { + type RenamedFoo = Helper; + + #[derive(AsRef)] + struct FieldTypesWithRenamedInner(#[as_ref(i32, RenamedFoo)] Helper); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for FieldTypesWithRenamedInner { - fn as_ref(&self) -> &bool { - self.0.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for FieldTypesWithRenamedInner { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } } - } - #[test] - fn field_types_with_renamed_inner() { let item = FieldTypesWithRenamedInner(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -262,64 +284,97 @@ mod single_field { mod generic { use super::*; - #[derive(AsRef)] - struct Nothing(T); - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing(T); + let item = Nothing("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } - #[derive(AsRef)] - #[as_ref(forward)] - struct Forward(T); + #[test] + fn nothing_assoc() { + #[derive(AsRef)] + struct Nothing(T::Assoc); + + let item = Nothing::("test".to_owned()); + + assert!(ptr::eq(item.as_ref(), &item.0)); + } #[test] fn forward() { + #[derive(AsRef)] + #[as_ref(forward)] + struct Forward(T); + let item = Forward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - struct Field(#[as_ref] T); + #[test] + fn forward_assoc() { + #[derive(AsRef)] + #[as_ref(forward)] + struct Forward(T::Assoc); + + let item = Forward::("test".to_owned()); + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + } #[test] fn field() { + #[derive(AsRef)] + struct Field(#[as_ref] T); + let item = Field("test".to_owned()); assert!(ptr::eq(item.as_ref(), &item.0)); } - #[derive(AsRef)] - struct FieldForward(#[as_ref(forward)] T); - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward(#[as_ref(forward)] T); + let item = FieldForward("test".to_owned()); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - #[as_ref(i32, f64)] - struct Types(T); + #[test] + fn field_forward_assoc() { + #[derive(AsRef)] + struct FieldForward(#[as_ref(forward)] T::Assoc); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsRef for Types { - fn as_ref(&self) -> &bool { - self.0.as_ref() - } + let item = FieldForward::("test".to_owned()); + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); } #[test] fn types() { + #[derive(AsRef)] + #[as_ref(i32, f64)] + struct Types(T); + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsRef for Types { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } + } + let item = Types(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -329,31 +384,69 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - #[as_ref(Vec)] - struct TypesInner(Vec); + #[test] + fn types_assoc() { + #[derive(AsRef)] + #[as_ref(i32, f64)] + struct Types(T::Assoc); + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsRef for Types + where + T::Assoc: AsRef, + { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } + } + + let item = Types::<()>(Helper(1, 2.0, false)); + + let rf: &i32 = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + + let rf: &f64 = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + } #[test] fn types_inner() { + #[derive(AsRef)] + #[as_ref(Vec)] + struct TypesInner(Vec); + let item = TypesInner(vec![1i32]); assert!(ptr::eq(item.as_ref(), &item.0)); } - #[derive(AsRef)] - struct FieldTypes(#[as_ref(i32, f64)] T); + #[test] + fn types_inner_assoc() { + #[derive(AsRef)] + #[as_ref(Vec)] + struct TypesInner(Vec); - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsRef for FieldTypes { - fn as_ref(&self) -> &bool { - self.0.as_ref() - } + let item = TypesInner::(vec![1i32]); + + assert!(ptr::eq(item.as_ref(), &item.0)); } #[test] fn field_types() { + #[derive(AsRef)] + struct FieldTypes(#[as_ref(i32, f64)] T); + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsRef for FieldTypes { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } + } + let item = FieldTypes(Helper(1, 2.0, false)); let rf: &i32 = item.as_ref(); @@ -363,55 +456,93 @@ mod single_field { assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - struct FieldTypesInner(#[as_ref(Vec)] Vec); + #[test] + fn field_types_assoc() { + #[derive(AsRef)] + struct FieldTypes(#[as_ref(i32, f64)] T::Assoc); + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsRef for FieldTypes + where + T::Assoc: AsRef, + { + fn as_ref(&self) -> &bool { + self.0.as_ref() + } + } + + let item = FieldTypes::<()>(Helper(1, 2.0, false)); + + let rf: &i32 = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + + let rf: &f64 = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + } #[test] fn field_types_inner() { + #[derive(AsRef)] + struct FieldTypesInner(#[as_ref(Vec)] Vec); + let item = FieldTypesInner(vec![1i32]); assert!(ptr::eq(item.as_ref(), &item.0)); } - #[derive(AsRef)] - #[as_ref(i32)] - struct Lifetime<'a>(LifetimeHelper<'a>); + #[test] + fn field_types_inner_assoc() { + #[derive(AsRef)] + struct FieldTypesInner( + #[as_ref(Vec<::Assoc>)] Vec<::Assoc>, + ); + + let item = FieldTypesInner::(vec![1i32]); + + assert!(ptr::eq(item.as_ref(), &item.0)); + } #[test] fn lifetime() { + #[derive(AsRef)] + #[as_ref(i32)] + struct Lifetime<'a>(LifetimeHelper<'a>); + let item = Lifetime(LifetimeHelper(&0)); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } - #[derive(AsRef)] - struct FieldLifetime<'a>(#[as_ref(i32)] LifetimeHelper<'a>); - #[test] fn field_lifetime() { + #[derive(AsRef)] + struct FieldLifetime<'a>(#[as_ref(i32)] LifetimeHelper<'a>); + let item = FieldLifetime(LifetimeHelper(&0)); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } - #[derive(AsRef)] - #[as_ref([i32])] - struct ConstParam(ConstParamHelper); - #[test] fn const_param() { + #[derive(AsRef)] + #[as_ref([i32])] + struct ConstParam(ConstParamHelper); + let item = ConstParam(ConstParamHelper([])); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } - #[derive(AsRef)] - struct FieldConstParam( - #[as_ref([i32])] ConstParamHelper, - ); - #[test] fn field_const_param() { + #[derive(AsRef)] + struct FieldConstParam( + #[as_ref([i32])] ConstParamHelper, + ); + let item = FieldConstParam(ConstParamHelper([])); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); @@ -438,13 +569,13 @@ mod single_field { mod named { use super::*; - #[derive(AsRef)] - struct Nothing { - first: String, - } - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing { + first: String, + } + let item = Nothing { first: "test".to_owned(), }; @@ -452,14 +583,14 @@ mod single_field { assert!(ptr::eq(item.as_ref(), &item.first)); } - #[derive(AsRef)] - #[as_ref(forward)] - struct Forward { - first: String, - } - #[test] fn forward() { + #[derive(AsRef)] + #[as_ref(forward)] + struct Forward { + first: String, + } + let item = Forward { first: "test".to_owned(), }; @@ -468,14 +599,14 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - struct Field { - #[as_ref] - first: String, - } - #[test] fn field() { + #[derive(AsRef)] + struct Field { + #[as_ref] + first: String, + } + let item = Field { first: "test".to_owned(), }; @@ -483,14 +614,14 @@ mod single_field { assert!(ptr::eq(item.as_ref(), &item.first)); } - #[derive(AsRef)] - struct FieldForward { - #[as_ref(forward)] - first: String, - } - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward { + #[as_ref(forward)] + first: String, + } + let item = FieldForward { first: "test".to_owned(), }; @@ -499,31 +630,31 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - #[as_ref(i32, f64)] - struct Types { - first: Helper, - } + #[test] + fn types() { + #[derive(AsRef)] + #[as_ref(i32, f64)] + struct Types { + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for Types { - fn as_ref(&self) -> &bool { - self.first.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for Types { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } } - } - // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsRef for Types { - fn as_ref(&self) -> &Helper { - &self.first + // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsRef for Types { + fn as_ref(&self) -> &Helper { + &self.first + } } - } - #[test] - fn types() { let item = Types { first: Helper(1, 2.0, false), }; @@ -535,23 +666,23 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - #[as_ref(i32, Helper)] - struct TypesWithInner { - first: Helper, - } + #[test] + fn types_with_inner() { + #[derive(AsRef)] + #[as_ref(i32, Helper)] + struct TypesWithInner { + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for TypesWithInner { - fn as_ref(&self) -> &bool { - self.first.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for TypesWithInner { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } } - } - #[test] - fn types_with_inner() { let item = TypesWithInner { first: Helper(1, 2.0, false), }; @@ -563,25 +694,25 @@ mod single_field { assert!(ptr::eq(rf, &item.first)); } - type RenamedFoo = Helper; + #[test] + fn types_with_renamed_inner() { + type RenamedFoo = Helper; - #[derive(AsRef)] - #[as_ref(i32, RenamedFoo)] - struct TypesWithRenamedInner { - first: Helper, - } + #[derive(AsRef)] + #[as_ref(i32, RenamedFoo)] + struct TypesWithRenamedInner { + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for TypesWithRenamedInner { - fn as_ref(&self) -> &bool { - self.first.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for TypesWithRenamedInner { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } } - } - #[test] - fn types_with_renamed_inner() { let item = TypesWithRenamedInner { first: Helper(1, 2.0, false), }; @@ -593,31 +724,31 @@ mod single_field { assert!(ptr::eq(rf, &item.first)); } - #[derive(AsRef)] - struct FieldTypes { - #[as_ref(i32, f64)] - first: Helper, - } + #[test] + fn field_types() { + #[derive(AsRef)] + struct FieldTypes { + #[as_ref(i32, f64)] + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for FieldTypes { - fn as_ref(&self) -> &bool { - self.first.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for FieldTypes { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } } - } - // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, by - // producing a trait implementations conflict error during compilation, if it does. - impl AsRef for FieldTypes { - fn as_ref(&self) -> &Helper { - &self.first + // Asserts that the macro expansion doesn't generate an `AsRef` impl for the field type, + // by producing a trait implementations conflict error during compilation, if it does. + impl AsRef for FieldTypes { + fn as_ref(&self) -> &Helper { + &self.first + } } - } - #[test] - fn field_types() { let item = FieldTypes { first: Helper(1, 2.0, false), }; @@ -629,23 +760,23 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - struct FieldTypesWithInner { - #[as_ref(i32, Helper)] - first: Helper, - } + #[test] + fn field_types_with_inner() { + #[derive(AsRef)] + struct FieldTypesWithInner { + #[as_ref(i32, Helper)] + first: Helper, + } - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for FieldTypesWithInner { - fn as_ref(&self) -> &bool { - self.first.as_ref() + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for FieldTypesWithInner { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } } - } - #[test] - fn field_types_with_inner() { let item = FieldTypesWithInner { first: Helper(1, 2.0, false), }; @@ -657,23 +788,25 @@ mod single_field { assert!(ptr::eq(rf, &item.first)); } - #[derive(AsRef)] - struct FieldTypesWithRenamedInner { - #[as_ref(i32, RenamedFoo)] - first: Helper, - } + #[test] + fn field_types_with_renamed_inner() { + type RenamedFoo = Helper; - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding to - // the field type, by producing a trait implementations conflict error during compilation, - // if it does. - impl AsRef for FieldTypesWithRenamedInner { - fn as_ref(&self) -> &bool { - self.first.as_ref() + #[derive(AsRef)] + struct FieldTypesWithRenamedInner { + #[as_ref(i32, RenamedFoo)] + first: Helper, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding + // to the field type, by producing a trait implementations conflict error during + // compilation, if it does. + impl AsRef for FieldTypesWithRenamedInner { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } } - } - #[test] - fn field_types_with_renamed_inner() { let item = FieldTypesWithRenamedInner { first: Helper(1, 2.0, false), }; @@ -688,13 +821,13 @@ mod single_field { mod generic { use super::*; - #[derive(AsRef)] - struct Nothing { - first: T, - } - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing { + first: T, + } + let item = Nothing { first: "test".to_owned(), }; @@ -702,14 +835,28 @@ mod single_field { assert!(ptr::eq(item.as_ref(), &item.first)); } - #[derive(AsRef)] - #[as_ref(forward)] - struct Forward { - first: T, + #[test] + fn nothing_assoc() { + #[derive(AsRef)] + struct Nothing { + first: ::Assoc, + } + + let item = Nothing:: { + first: "test".to_owned(), + }; + + assert!(ptr::eq(item.as_ref(), &item.first)); } #[test] fn forward() { + #[derive(AsRef)] + #[as_ref(forward)] + struct Forward { + first: T, + } + let item = Forward { first: "test".to_owned(), }; @@ -718,14 +865,30 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - struct Field { - #[as_ref] - first: T, + #[test] + fn forward_assoc() { + #[derive(AsRef)] + #[as_ref(forward)] + struct Forward { + first: T::Assoc, + } + + let item = Forward:: { + first: "test".to_owned(), + }; + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); } #[test] fn field() { + #[derive(AsRef)] + struct Field { + #[as_ref] + first: T, + } + let item = Field { first: "test".to_owned(), }; @@ -733,14 +896,14 @@ mod single_field { assert!(ptr::eq(item.as_ref(), &item.first)); } - #[derive(AsRef)] - struct FieldForward { - #[as_ref(forward)] - first: T, - } - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward { + #[as_ref(forward)] + first: T, + } + let item = FieldForward { first: "test".to_owned(), }; @@ -749,23 +912,39 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - #[as_ref(i32, f64)] - struct Types { - first: T, - } - - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsRef for Types { - fn as_ref(&self) -> &bool { - self.first.as_ref() + #[test] + fn field_forward_assoc() { + #[derive(AsRef)] + struct FieldForward { + #[as_ref(forward)] + first: T::Assoc, } + + let item = FieldForward:: { + first: "test".to_owned(), + }; + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); } #[test] fn types() { + #[derive(AsRef)] + #[as_ref(i32, f64)] + struct Types { + first: T, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsRef for Types { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } + } + let item = Types { first: Helper(1, 2.0, false), }; @@ -777,36 +956,80 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - #[as_ref(Vec)] - struct TypesInner { - first: Vec, + #[test] + fn types_assoc() { + #[derive(AsRef)] + #[as_ref(i32, f64)] + struct Types { + first: T::Assoc, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsRef for Types + where + T::Assoc: AsRef, + { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } + } + + let item = Types::<()> { + first: Helper(1, 2.0, false), + }; + + let rf: &i32 = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); + + let rf: &f64 = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); } #[test] fn types_inner() { + #[derive(AsRef)] + #[as_ref(Vec)] + struct TypesInner { + first: Vec, + } + let item = TypesInner { first: vec![1i32] }; assert!(ptr::eq(item.as_ref(), &item.first)); } - #[derive(AsRef)] - struct FieldTypes { - #[as_ref(i32, f64)] - first: T, - } - - // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl forwarding - // to the field type, by producing a trait implementations conflict error during - // compilation, if it does. - impl> AsRef for FieldTypes { - fn as_ref(&self) -> &bool { - self.first.as_ref() + #[test] + fn types_inner_assoc() { + #[derive(AsRef)] + #[as_ref(Vec)] + struct TypesInner { + first: Vec, } + + let item = TypesInner:: { first: vec![1i32] }; + + assert!(ptr::eq(item.as_ref(), &item.first)); } #[test] fn field_types() { + #[derive(AsRef)] + struct FieldTypes { + #[as_ref(i32, f64)] + first: T, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl> AsRef for FieldTypes { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } + } + let item = FieldTypes { first: Helper(1, 2.0, false), }; @@ -818,27 +1041,71 @@ mod single_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - struct FieldTypesInner { - #[as_ref(Vec)] - first: Vec, + #[test] + fn field_types_assoc() { + #[derive(AsRef)] + struct FieldTypes { + #[as_ref(i32, f64)] + first: T::Assoc, + } + + // Asserts that the macro expansion doesn't generate a blanket `AsRef` impl + // forwarding to the field type, by producing a trait implementations conflict error + // during compilation, if it does. + impl AsRef for FieldTypes + where + T::Assoc: AsRef, + { + fn as_ref(&self) -> &bool { + self.first.as_ref() + } + } + + let item = FieldTypes::<()> { + first: Helper(1, 2.0, false), + }; + + let rf: &i32 = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); + + let rf: &f64 = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); } #[test] fn field_types_inner() { + #[derive(AsRef)] + struct FieldTypesInner { + #[as_ref(Vec)] + first: Vec, + } + let item = FieldTypesInner { first: vec![1i32] }; assert!(ptr::eq(item.as_ref(), &item.first)); } - #[derive(AsRef)] - #[as_ref(i32)] - struct Lifetime<'a> { - first: LifetimeHelper<'a>, + #[test] + fn field_types_inner_assoc() { + #[derive(AsRef)] + struct FieldTypesInner { + #[as_ref(Vec<::Assoc>)] + first: Vec<::Assoc>, + } + + let item = FieldTypesInner:: { first: vec![1i32] }; + + assert!(ptr::eq(item.as_ref(), &item.first)); } #[test] fn lifetime() { + #[derive(AsRef)] + #[as_ref(i32)] + struct Lifetime<'a> { + first: LifetimeHelper<'a>, + } + let item = Lifetime { first: LifetimeHelper(&0), }; @@ -846,14 +1113,14 @@ mod single_field { assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } - #[derive(AsRef)] - struct FieldLifetime<'a> { - #[as_ref(i32)] - first: LifetimeHelper<'a>, - } - #[test] fn field_lifetime() { + #[derive(AsRef)] + struct FieldLifetime<'a> { + #[as_ref(i32)] + first: LifetimeHelper<'a>, + } + let item = FieldLifetime { first: LifetimeHelper(&0), }; @@ -861,14 +1128,14 @@ mod single_field { assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } - #[derive(AsRef)] - #[as_ref([i32])] - struct ConstParam { - first: ConstParamHelper, - } - #[test] fn const_param() { + #[derive(AsRef)] + #[as_ref([i32])] + struct ConstParam { + first: ConstParamHelper, + } + let item = ConstParam { first: ConstParamHelper([]), }; @@ -876,14 +1143,14 @@ mod single_field { assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } - #[derive(AsRef)] - struct FieldConstParam { - #[as_ref([i32])] - first: ConstParamHelper, - } - #[test] fn field_const_param() { + #[derive(AsRef)] + struct FieldConstParam { + #[as_ref([i32])] + first: ConstParamHelper, + } + let item = FieldConstParam { first: ConstParamHelper([]), }; @@ -921,84 +1188,84 @@ mod multi_field { mod tuple { use super::*; - #[derive(AsRef)] - struct Nothing(String, i32); - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing(String, i32); + let item = Nothing("test".to_owned(), 0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } - #[derive(AsRef)] - struct Skip(String, i32, #[as_ref(skip)] f64); + #[test] + fn skip() { + #[derive(AsRef)] + struct Skip(String, i32, #[as_ref(skip)] f64); - // Asserts that the macro expansion doesn't generate `AsRef` impl for the skipped field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsRef for Skip { - fn as_ref(&self) -> &f64 { - &self.2 + // Asserts that the macro expansion doesn't generate `AsRef` impl for the skipped field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsRef for Skip { + fn as_ref(&self) -> &f64 { + &self.2 + } } - } - #[test] - fn skip() { let item = Skip("test".to_owned(), 0, 0.0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } - #[derive(AsRef)] - struct Field(#[as_ref] String, #[as_ref] i32, f64); + #[test] + fn field() { + #[derive(AsRef)] + struct Field(#[as_ref] String, #[as_ref] i32, f64); - // Asserts that the macro expansion doesn't generate `AsRef` impl for the third field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsRef for Field { - fn as_ref(&self) -> &f64 { - &self.2 + // Asserts that the macro expansion doesn't generate `AsRef` impl for the third field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsRef for Field { + fn as_ref(&self) -> &f64 { + &self.2 + } } - } - #[test] - fn field() { let item = Field("test".to_owned(), 0, 0.0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } - #[derive(AsRef)] - struct FieldForward(#[as_ref(forward)] String, i32); - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward(#[as_ref(forward)] String, i32); + let item = FieldForward("test".to_owned(), 0); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } - type RenamedString = String; + #[test] + fn types() { + type RenamedString = String; - #[derive(AsRef)] - struct Types( - #[as_ref(str, RenamedString)] String, - #[as_ref([u8])] Vec, - ); + #[derive(AsRef)] + struct Types( + #[as_ref(str, RenamedString)] String, + #[as_ref([u8])] Vec, + ); - // Asserts that the macro expansion doesn't generate `AsRef` impl for the field type, by - // producing trait implementations conflict error during compilation, if it does. - impl AsRef> for Types { - fn as_ref(&self) -> &Vec { - &self.1 + // Asserts that the macro expansion doesn't generate `AsRef` impl for the field type, by + // producing trait implementations conflict error during compilation, if it does. + impl AsRef> for Types { + fn as_ref(&self) -> &Vec { + &self.1 + } } - } - #[test] - fn types() { let item = Types("test".to_owned(), vec![0]); let rf: &str = item.as_ref(); @@ -1014,55 +1281,66 @@ mod multi_field { mod generic { use super::*; - #[derive(AsRef)] - struct Nothing(Vec, VecDeque); - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing(Vec, VecDeque); + let item = Nothing(vec![1], VecDeque::from([2])); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } - #[derive(AsRef)] - struct Skip(Vec, VecDeque, #[as_ref(skip)] V); - #[test] fn skip() { + #[derive(AsRef)] + struct Skip(Vec, VecDeque, #[as_ref(skip)] V); + let item = Skip(vec![1], VecDeque::from([2]), 0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } - #[derive(AsRef)] - struct Field(#[as_ref] Vec, #[as_ref] VecDeque, V); - #[test] fn field() { + #[derive(AsRef)] + struct Field(#[as_ref] Vec, #[as_ref] VecDeque, V); + let item = Field(vec![1], VecDeque::from([2]), 0); assert!(ptr::eq(item.as_ref(), &item.0)); assert!(ptr::eq(item.as_ref(), &item.1)); } - #[derive(AsRef)] - struct FieldForward(#[as_ref(forward)] T, U); - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward(#[as_ref(forward)] T, U); + let item = FieldForward("test".to_owned(), 0); let rf: &str = item.as_ref(); assert!(ptr::eq(rf, item.0.as_ref())); } - #[derive(AsRef)] - struct Types(#[as_ref(str)] T, #[as_ref([u8])] U); + #[test] + fn field_forward_assoc() { + #[derive(AsRef)] + struct FieldForward(#[as_ref(forward)] T::Assoc, U); + + let item = FieldForward::("test".to_owned(), 0); + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + } #[test] fn types() { + #[derive(AsRef)] + struct Types(#[as_ref(str)] T, #[as_ref([u8])] U); + let item = Types("test".to_owned(), vec![0u8]); let rf: &str = item.as_ref(); @@ -1072,14 +1350,31 @@ mod multi_field { assert!(ptr::eq(rf, item.1.as_ref())); } - #[derive(AsRef)] - struct TypesWithInner( - #[as_ref(Vec, [T])] Vec, - #[as_ref(str)] U, - ); + #[test] + fn types_assoc() { + #[derive(AsRef)] + struct Types( + #[as_ref(str)] ::Assoc, + #[as_ref([u8])] Vec, + ); + + let item = Types::("test".to_owned(), vec![0u8]); + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + + let rf: &[u8] = item.as_ref(); + assert!(ptr::eq(rf, item.1.as_ref())); + } #[test] fn types_with_inner() { + #[derive(AsRef)] + struct TypesWithInner( + #[as_ref(Vec, [T])] Vec, + #[as_ref(str)] U, + ); + let item = TypesWithInner(vec![1i32], "a".to_owned()); let rf: &Vec = item.as_ref(); @@ -1092,15 +1387,45 @@ mod multi_field { assert!(ptr::eq(rf, item.1.as_ref())); } - #[derive(AsRef)] - struct FieldNonGeneric(#[as_ref([T])] Vec, T); + #[test] + fn types_with_inner_assoc() { + #[derive(AsRef)] + struct TypesWithInner( + #[as_ref(Vec, [T::Assoc])] Vec, + #[as_ref(str)] U::Assoc, + ); + + let item = TypesWithInner::(vec![1i32], "a".to_owned()); + + let rf: &Vec = item.as_ref(); + assert!(ptr::eq(rf, &item.0)); + + let rf: &[i32] = item.as_ref(); + assert!(ptr::eq(rf, item.0.as_ref())); + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.1.as_ref())); + } #[test] fn field_non_generic() { + #[derive(AsRef)] + struct FieldNonGeneric(#[as_ref([T])] Vec, T); + let item = FieldNonGeneric(vec![], 2i32); assert!(ptr::eq(item.as_ref(), item.0.as_ref())); } + + #[test] + fn field_non_generic_assoc() { + #[derive(AsRef)] + struct FieldNonGeneric(#[as_ref([T::Assoc])] Vec, T); + + let item = FieldNonGeneric::(vec![], 2u8); + + assert!(ptr::eq(item.as_ref(), item.0.as_ref())); + } } #[cfg(nightly)] @@ -1115,14 +1440,14 @@ mod multi_field { mod named { use super::*; - #[derive(AsRef)] - struct Nothing { - first: String, - second: i32, - } - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing { + first: String, + second: i32, + } + let item = Nothing { first: "test".to_owned(), second: 0, @@ -1132,24 +1457,24 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), &item.second)); } - #[derive(AsRef)] - struct Skip { - first: String, - second: i32, - #[as_ref(skip)] - third: f64, - } + #[test] + fn skip() { + #[derive(AsRef)] + struct Skip { + first: String, + second: i32, + #[as_ref(skip)] + third: f64, + } - // Asserts that the macro expansion doesn't generate `AsRef` impl for the skipped field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsRef for Skip { - fn as_ref(&self) -> &f64 { - &self.third + // Asserts that the macro expansion doesn't generate `AsRef` impl for the skipped field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsRef for Skip { + fn as_ref(&self) -> &f64 { + &self.third + } } - } - #[test] - fn skip() { let item = Skip { first: "test".to_owned(), second: 0, @@ -1160,25 +1485,25 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), &item.second)); } - #[derive(AsRef)] - struct Field { - #[as_ref] - first: String, - #[as_ref] - second: i32, - third: f64, - } + #[test] + fn field() { + #[derive(AsRef)] + struct Field { + #[as_ref] + first: String, + #[as_ref] + second: i32, + third: f64, + } - // Asserts that the macro expansion doesn't generate `AsRef` impl for the `third` field, by - // producing trait implementations conflict error during compilation, if it does. - impl AsRef for Field { - fn as_ref(&self) -> &f64 { - &self.third + // Asserts that the macro expansion doesn't generate `AsRef` impl for the `third` field, + // by producing trait implementations conflict error during compilation, if it does. + impl AsRef for Field { + fn as_ref(&self) -> &f64 { + &self.third + } } - } - #[test] - fn field() { let item = Field { first: "test".to_owned(), second: 0, @@ -1189,15 +1514,15 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), &item.second)); } - #[derive(AsRef)] - struct FieldForward { - #[as_ref(forward)] - first: String, - second: i32, - } - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward { + #[as_ref(forward)] + first: String, + second: i32, + } + let item = FieldForward { first: "test".to_owned(), second: 0, @@ -1207,26 +1532,26 @@ mod multi_field { assert!(ptr::eq(rf, item.first.as_ref())); } - type RenamedString = String; + #[test] + fn types() { + type RenamedString = String; - #[derive(AsRef)] - struct Types { - #[as_ref(str, RenamedString)] - first: String, - #[as_ref([u8])] - second: Vec, - } + #[derive(AsRef)] + struct Types { + #[as_ref(str, RenamedString)] + first: String, + #[as_ref([u8])] + second: Vec, + } - // Asserts that the macro expansion doesn't generate `AsRef` impl for the field type, by - // producing trait implementations conflict error during compilation, if it does. - impl AsRef> for Types { - fn as_ref(&self) -> &Vec { - &self.second + // Asserts that the macro expansion doesn't generate `AsRef` impl for the field type, by + // producing trait implementations conflict error during compilation, if it does. + impl AsRef> for Types { + fn as_ref(&self) -> &Vec { + &self.second + } } - } - #[test] - fn types() { let item = Types { first: "test".to_owned(), second: vec![0u8], @@ -1245,14 +1570,14 @@ mod multi_field { mod generic { use super::*; - #[derive(AsRef)] - struct Nothing { - first: Vec, - second: VecDeque, - } - #[test] fn nothing() { + #[derive(AsRef)] + struct Nothing { + first: Vec, + second: VecDeque, + } + let item = Nothing { first: vec![1], second: VecDeque::from([2]), @@ -1262,16 +1587,16 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), &item.second)); } - #[derive(AsRef)] - struct Skip { - first: Vec, - second: VecDeque, - #[as_ref(skip)] - third: V, - } - #[test] fn skip() { + #[derive(AsRef)] + struct Skip { + first: Vec, + second: VecDeque, + #[as_ref(skip)] + third: V, + } + let item = Skip { first: vec![1], second: VecDeque::from([2]), @@ -1282,17 +1607,17 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), &item.second)); } - #[derive(AsRef)] - struct Field { - #[as_ref] - first: Vec, - #[as_ref] - second: VecDeque, - third: V, - } - #[test] fn field() { + #[derive(AsRef)] + struct Field { + #[as_ref] + first: Vec, + #[as_ref] + second: VecDeque, + third: V, + } + let item = Field { first: vec![1], second: VecDeque::from([2]), @@ -1303,15 +1628,15 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), &item.second)); } - #[derive(AsRef)] - struct FieldForward { - #[as_ref(forward)] - first: T, - second: U, - } - #[test] fn field_forward() { + #[derive(AsRef)] + struct FieldForward { + #[as_ref(forward)] + first: T, + second: U, + } + let item = FieldForward { first: "test".to_owned(), second: 0, @@ -1321,16 +1646,34 @@ mod multi_field { assert!(ptr::eq(rf, item.first.as_ref())); } - #[derive(AsRef)] - struct Types { - #[as_ref(str)] - first: T, - #[as_ref([u8])] - second: U, + #[test] + fn field_forward_assoc() { + #[derive(AsRef)] + struct FieldForward { + #[as_ref(forward)] + first: T::Assoc, + second: U, + } + + let item = FieldForward:: { + first: "test".to_owned(), + second: 0, + }; + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); } #[test] fn types() { + #[derive(AsRef)] + struct Types { + #[as_ref(str)] + first: T, + #[as_ref([u8])] + second: U, + } + let item = Types { first: "test".to_owned(), second: vec![0u8], @@ -1343,16 +1686,38 @@ mod multi_field { assert!(ptr::eq(rf, item.second.as_ref())); } - #[derive(AsRef)] - struct TypesWithInner { - #[as_ref(Vec, [T])] - first: Vec, - #[as_ref(str)] - second: U, + #[test] + fn types_assoc() { + #[derive(AsRef)] + struct Types { + #[as_ref(str)] + first: T::Assoc, + #[as_ref([u8])] + second: Vec<::Assoc>, + } + + let item = Types:: { + first: "test".to_owned(), + second: vec![0u8], + }; + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); + + let rf: &[u8] = item.as_ref(); + assert!(ptr::eq(rf, item.second.as_ref())); } #[test] fn types_with_inner() { + #[derive(AsRef)] + struct TypesWithInner { + #[as_ref(Vec, [T])] + first: Vec, + #[as_ref(str)] + second: U, + } + let item = TypesWithInner { first: vec![1i32], second: "a".to_owned(), @@ -1368,15 +1733,40 @@ mod multi_field { assert!(ptr::eq(rf, item.second.as_ref())); } - #[derive(AsRef)] - struct FieldNonGeneric { - #[as_ref([T])] - first: Vec, - second: T, + #[test] + fn types_with_inner_assoc() { + #[derive(AsRef)] + struct TypesWithInner { + #[as_ref(Vec<::Assoc>, [::Assoc])] + first: Vec<::Assoc>, + #[as_ref(str)] + second: U::Assoc, + } + + let item = TypesWithInner:: { + first: vec![1i32], + second: "a".to_owned(), + }; + + let rf: &Vec = item.as_ref(); + assert!(ptr::eq(rf, &item.first)); + + let rf: &[i32] = item.as_ref(); + assert!(ptr::eq(rf, item.first.as_ref())); + + let rf: &str = item.as_ref(); + assert!(ptr::eq(rf, item.second.as_ref())); } #[test] fn field_non_generic() { + #[derive(AsRef)] + struct FieldNonGeneric { + #[as_ref([T])] + first: Vec, + second: T, + } + let item = FieldNonGeneric { first: vec![], second: 2i32, @@ -1384,6 +1774,23 @@ mod multi_field { assert!(ptr::eq(item.as_ref(), item.first.as_ref())); } + + #[test] + fn field_non_generic_assoc() { + #[derive(AsRef)] + struct FieldNonGeneric { + #[as_ref([::Assoc])] + first: Vec, + second: T, + } + + let item = FieldNonGeneric:: { + first: vec![], + second: 2u8, + }; + + assert!(ptr::eq(item.as_ref(), item.first.as_ref())); + } } #[cfg(nightly)]