Repository: JelteF/derive_more
Pull request #474 (2025-05-27 15:01:46)

Consider associative types in `utils::GenericsSearch`
Revealed from #473

## Synopsis

`utils::GenericsSearch` doesn't consider associative type, leading to missing trait bounds in `AsRef`/`AsMut` expansions.

```rust
#[derive(AsRef)]
#[as_ref(forward)]
struct Forward<T: Some> {
    first: T::Assoc,
}
```
expands as:
```rust
#[allow(deprecated)]
#[allow(unreachable_code)]
#[automatically_derived]
impl<T: Some, __AsT: ?derive_more::core::marker::Sized> derive_more::core::convert::AsRef<__AsT> for Forward<T>
{
    #[inline]
    fn as_ref(&self) -> &__AsT { <T::Assoc as derive_more::core::convert::AsRef<__AsT>>::as_ref(&self.first) }
}
```
but should expand as:
```rust
#[allow(deprecated)]
#[allow(unreachable_code)]
#[automatically_derived]
impl<T: Some, __AsT: ?derive_more::core::marker::Sized> derive_more::core::convert::AsRef<__AsT> for Forward<T>
where
    T::Assoc: derive_more::core::convert::AsRef<__AsT>,
{
    #[inline]
    fn as_ref(&self) -> &__AsT { <T::Assoc as derive_more::core::convert::AsRef<__AsT>>::as_ref(&self.first) }
}
```

## Solution

This PR fixes this situation and covers associative types usage in `AsRef`/`AsMut` tests.

## Additionally

Improves `utils::GenericsSearch` performance by early returns (stop `Visit`ing whenever something is found).

Also, unit tests for `utils::GenericsSearch` are added.


## Checklist

- [x] ~~Documentation is updated~~ (not required)
- [x] Tests are added/updated
- [x] [CHANGELOG entry](/CHANGELOG.md) is added



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b2db57..37cd054 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 21d653a..53a417c 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 72bbb83..5e5ed68 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 d178c33..825d95d 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! { <T> };
+            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<T, 'a> },
+                parse_quote! { path::<'a, T>::Type },
+                parse_quote! { <Self as Trait<'a, T>>::Type },
+                parse_quote! { <Self as Trait>::Type<T, 'a> },
+                parse_quote! { T::Type },
+                parse_quote! { <T as Trait>::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! { <Self as Trait<'a>>::Type },
+                parse_quote! { <Self as Trait>::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! { <const N: usize> };
+            let search = GenericsSearch::from(&generics);
+
+            for input in [
+                parse_quote! { [_; N] },
+                parse_quote! { Type<N> },
+                #[cfg(feature = "testing-helpers")] // requires `syn/full`
+                parse_quote! { Type<{ N }> },
+                parse_quote! { path::Type<N> },
+                #[cfg(feature = "testing-helpers")] // requires `syn/full`
+                parse_quote! { path::Type<{ N }> },
+                parse_quote! { path::<N>::Type },
+                #[cfg(feature = "testing-helpers")] // requires `syn/full`
+                parse_quote! { path::<{ N }>::Type },
+                parse_quote! { <Self as Trait<N>>::Type },
+                #[cfg(feature = "testing-helpers")] // requires `syn/full`
+                parse_quote! { <Self as Trait<{ N }>>::Type },
+                parse_quote! { <Self as Trait>::Type<N> },
+                #[cfg(feature = "testing-helpers")] // requires `syn/full`
+                parse_quote! { <Self as Trait>::Type<{ N }> },
+            ] {
+                assert!(
+                    search.any_in(&input),
+                    "cannot find const parameter `N` in type `{}`",
+                    input.into_token_stream(),
+                );
+            }
         }
     }
 }


Test patch:
diff --git a/tests/as_mut.rs b/tests/as_mut.rs
index 5bb5c4d..ebfb633 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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>(T);
-
             #[test]
             fn nothing() {
+                #[derive(AsMut)]
+                struct Nothing<T>(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>(T);
+            #[test]
+            fn nothing_assoc() {
+                #[derive(AsMut)]
+                struct Nothing<T: Some>(T::Assoc);
+
+                let mut item = Nothing::<bool>("test".to_owned());
+
+                assert!(ptr::eq(item.as_mut(), &mut item.0));
+            }
 
             #[test]
             fn forward() {
+                #[derive(AsMut)]
+                #[as_mut(forward)]
+                struct Forward<T>(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<T>(#[as_mut] T);
+            #[test]
+            fn forward_assoc() {
+                #[derive(AsMut)]
+                #[as_mut(forward)]
+                struct Forward<T: Some>(T::Assoc);
+
+                let mut item = Forward::<bool>("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<T>(#[as_mut] T);
+
                 let mut item = Field("test".to_owned());
 
                 assert!(ptr::eq(item.as_mut(), &mut item.0));
             }
 
-            #[derive(AsMut)]
-            struct FieldForward<T>(#[as_mut(forward)] T);
-
             #[test]
             fn field_forward() {
+                #[derive(AsMut)]
+                struct FieldForward<T>(#[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>(T);
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsMut)]
+                struct FieldForward<T: Some>(#[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<T: AsMut<bool>> AsMut<bool> for Types<T> {
-                fn as_mut(&mut self) -> &mut bool {
-                    self.0.as_mut()
-                }
+                let mut item = FieldForward::<bool>("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>(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<T: AsMut<bool>> AsMut<bool> for Types<T> {
+                    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<T>)]
-            struct TypesInner<T>(Vec<T>);
+            #[test]
+            fn types_assoc() {
+                #[derive(AsMut)]
+                #[as_mut(i32, f64)]
+                struct Types<T: Some>(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<T: Some> AsMut<bool> for Types<T>
+                where
+                    T::Assoc: AsMut<bool>,
+                {
+                    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<T>)]
+                struct TypesInner<T>(Vec<T>);
+
                 let mut item = TypesInner(vec![1i32]);
 
                 assert!(ptr::eq(item.as_mut(), &mut item.0));
             }
 
-            #[derive(AsMut)]
-            struct FieldTypes<T>(#[as_mut(i32, f64)] T);
+            #[test]
+            fn types_inner_assoc() {
+                #[derive(AsMut)]
+                #[as_mut(Vec<T::Assoc>)]
+                struct TypesInner<T: Some>(Vec<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<T: AsMut<bool>> AsMut<bool> for FieldTypes<T> {
-                fn as_mut(&mut self) -> &mut bool {
-                    self.0.as_mut()
-                }
+                let mut item = TypesInner::<u8>(vec![1i32]);
+
+                assert!(ptr::eq(item.as_mut(), &mut item.0));
             }
 
             #[test]
             fn field_types() {
+                #[derive(AsMut)]
+                struct FieldTypes<T>(#[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<T: AsMut<bool>> AsMut<bool> for FieldTypes<T> {
+                    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<T>(#[as_mut(Vec<T>)] Vec<T>);
+            #[test]
+            fn field_types_assoc() {
+                #[derive(AsMut)]
+                struct FieldTypes<T: Some>(#[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<T: Some> AsMut<bool> for FieldTypes<T>
+                where
+                    T::Assoc: AsMut<bool>,
+                {
+                    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<T>(#[as_mut(Vec<T>)] Vec<T>);
+
                 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<T: Some>(
+                    #[as_mut(Vec<<T as Some>::Assoc>)] Vec<<T as Some>::Assoc>,
+                );
+
+                let mut item = FieldTypesInner::<u8>(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<const N: usize>(ConstParamHelper<N>);
-
             #[test]
             fn const_param() {
+                #[derive(AsMut)]
+                #[as_mut([i32])]
+                struct ConstParam<const N: usize>(ConstParamHelper<N>);
+
                 let mut item = ConstParam(ConstParamHelper([]));
 
                 assert!(ptr::eq(item.as_mut(), item.0.as_mut()));
             }
 
-            #[derive(AsMut)]
-            struct FieldConstParam<const N: usize>(
-                #[as_mut([i32])] ConstParamHelper<N>,
-            );
-
             #[test]
             fn field_const_param() {
+                #[derive(AsMut)]
+                struct FieldConstParam<const N: usize>(
+                    #[as_mut([i32])] ConstParamHelper<N>,
+                );
+
                 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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<T> {
-                first: T,
-            }
-
             #[test]
             fn nothing() {
+                #[derive(AsMut)]
+                struct Nothing<T> {
+                    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<T> {
-                first: T,
+            #[test]
+            fn nothing_assoc() {
+                #[derive(AsMut)]
+                struct Nothing<T: Some> {
+                    first: <T as Some>::Assoc,
+                }
+
+                let mut item = Nothing::<bool> {
+                    first: "test".to_owned(),
+                };
+
+                assert!(ptr::eq(item.as_mut(), &mut item.first));
             }
 
             #[test]
             fn struct_forward() {
+                #[derive(AsMut)]
+                #[as_mut(forward)]
+                struct Forward<T> {
+                    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<T> {
-                #[as_mut]
-                first: T,
+            #[test]
+            fn struct_forward_assoc() {
+                #[derive(AsMut)]
+                #[as_mut(forward)]
+                struct Forward<T: Some> {
+                    first: T::Assoc,
+                }
+
+                let mut item = Forward::<bool> {
+                    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<T> {
+                    #[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<T> {
-                #[as_mut(forward)]
-                first: T,
-            }
-
             #[test]
             fn field_forward() {
+                #[derive(AsMut)]
+                struct FieldForward<T> {
+                    #[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<T> {
-                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<T: AsMut<bool>> AsMut<bool> for Types<T> {
-                fn as_mut(&mut self) -> &mut bool {
-                    self.first.as_mut()
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsMut)]
+                struct FieldForward<T: Some> {
+                    #[as_mut(forward)]
+                    first: T::Assoc,
                 }
+
+                let mut item = FieldForward::<bool> {
+                    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<T> {
+                    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<T: AsMut<bool>> AsMut<bool> for Types<T> {
+                    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<T>)]
-            struct TypesInner<T> {
-                first: Vec<T>,
+            #[test]
+            fn types_assoc() {
+                #[derive(AsMut)]
+                #[as_mut(i32, f64)]
+                struct Types<T: Some> {
+                    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<T: Some> AsMut<bool> for Types<T>
+                where
+                    T::Assoc: AsMut<bool>,
+                {
+                    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<T>)]
+                struct TypesInner<T> {
+                    first: Vec<T>,
+                }
+
                 let mut item = TypesInner { first: vec![1i32] };
 
                 assert!(ptr::eq(item.as_mut(), &mut item.first));
             }
 
-            #[derive(AsMut)]
-            struct FieldTypes<T> {
-                #[as_mut(i32, f64)]
-                first: T,
+            #[test]
+            fn types_inner_assoc() {
+                #[derive(AsMut)]
+                #[as_mut(Vec<T::Assoc>)]
+                struct TypesInner<T: Some> {
+                    first: Vec<T::Assoc>,
+                }
+
+                let mut item = TypesInner::<u8> { 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<T: AsMut<bool>> AsMut<bool> for FieldTypes<T> {
-                fn as_mut(&mut self) -> &mut bool {
-                    self.first.as_mut()
+            #[test]
+            fn field_types() {
+                #[derive(AsMut)]
+                struct FieldTypes<T> {
+                    #[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<T: AsMut<bool>> AsMut<bool> for FieldTypes<T> {
+                    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<T> {
-                #[as_mut(Vec<T>)]
-                first: Vec<T>,
+            #[test]
+            fn field_types_assoc() {
+                #[derive(AsMut)]
+                struct FieldTypes<T: Some> {
+                    #[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<T: Some> AsMut<bool> for FieldTypes<T>
+                where
+                    T::Assoc: AsMut<bool>,
+                {
+                    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<T> {
+                    #[as_mut(Vec<T>)]
+                    first: Vec<T>,
+                }
+
                 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<T: Some> {
+                    #[as_mut(Vec<<T as Some>::Assoc>)]
+                    first: Vec<<T as Some>::Assoc>,
+                }
+
+                let mut item = FieldTypesInner::<u8> { 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<const N: usize> {
-                first: ConstParamHelper<N>,
-            }
-
             #[test]
             fn const_param() {
+                #[derive(AsMut)]
+                #[as_mut([i32])]
+                struct ConstParam<const N: usize> {
+                    first: ConstParamHelper<N>,
+                }
+
                 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<const N: usize> {
-                #[as_mut([i32])]
-                first: ConstParamHelper<N>,
-            }
-
             #[test]
             fn field_const_param() {
+                #[derive(AsMut)]
+                struct FieldConstParam<const N: usize> {
+                    #[as_mut([i32])]
+                    first: ConstParamHelper<N>,
+                }
+
                 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<f64> 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<f64> 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<f64> 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<f64> 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<u8>,
-        );
+            #[derive(AsMut)]
+            struct Types(
+                #[as_mut(str, RenamedString)] String,
+                #[as_mut([u8])] Vec<u8>,
+            );
 
-        // 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<Vec<u8>> for Types {
-            fn as_mut(&mut self) -> &mut Vec<u8> {
-                &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<Vec<u8>> for Types {
+                fn as_mut(&mut self) -> &mut Vec<u8> {
+                    &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<T, U>(Vec<T>, VecDeque<U>);
-
             #[test]
             fn nothing() {
+                #[derive(AsMut)]
+                struct Nothing<T, U>(Vec<T>, VecDeque<U>);
+
                 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<T, U, V>(Vec<T>, VecDeque<U>, #[as_mut(skip)] V);
-
             #[test]
             fn skip() {
+                #[derive(AsMut)]
+                struct Skip<T, U, V>(Vec<T>, VecDeque<U>, #[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<T, U, V>(#[as_mut] Vec<T>, #[as_mut] VecDeque<U>, V);
-
             #[test]
             fn field() {
+                #[derive(AsMut)]
+                struct Field<T, U, V>(#[as_mut] Vec<T>, #[as_mut] VecDeque<U>, 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<T, U>(#[as_mut(forward)] T, U);
-
             #[test]
             fn field_forward() {
+                #[derive(AsMut)]
+                struct FieldForward<T, U>(#[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<T, U>(#[as_mut(str)] T, #[as_mut([u8])] U);
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsMut)]
+                struct FieldForward<T: Some, U>(#[as_mut(forward)] T::Assoc, U);
+
+                let mut item = FieldForward::<bool, _>("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<T, U>(#[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<T, U>(
-                #[as_mut(Vec<T>, [T])] Vec<T>,
-                #[as_mut(str)] U,
-            );
+            #[test]
+            fn types_assoc() {
+                #[derive(AsMut)]
+                struct Types<T: Some, U: Some + ?Sized>(
+                    #[as_mut(str)] <T as Some>::Assoc,
+                    #[as_mut([u8])] Vec<U::Assoc>,
+                );
+
+                let mut item = Types::<bool, str>("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<T, U>(
+                    #[as_mut(Vec<T>, [T])] Vec<T>,
+                    #[as_mut(str)] U,
+                );
+
                 let mut item = TypesWithInner(vec![1i32], "a".to_owned());
 
                 let rf: &mut Vec<i32> = item.as_mut();
@@ -1099,15 +1394,45 @@ mod multi_field {
                 assert!(ptr::eq(rf, item.1.as_mut()));
             }
 
-            #[derive(AsMut)]
-            struct FieldNonGeneric<T>(#[as_mut([T])] Vec<i32>, T);
+            #[test]
+            fn types_with_inner_assoc() {
+                #[derive(AsMut)]
+                struct TypesWithInner<T: Some, U: Some>(
+                    #[as_mut(Vec<T::Assoc>, [T::Assoc])] Vec<T::Assoc>,
+                    #[as_mut(str)] U::Assoc,
+                );
+
+                let mut item = TypesWithInner::<u8, bool>(vec![1i32], "a".to_owned());
+
+                let rf: &mut Vec<i32> = 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<T>(#[as_mut([T])] Vec<i32>, 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<T: Some>(#[as_mut([T::Assoc])] Vec<i32>, T);
+
+                let mut item = FieldNonGeneric::<u8>(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<f64> 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<f64> 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<f64> 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<f64> 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<u8>,
-        }
+            #[derive(AsMut)]
+            struct Types {
+                #[as_mut(str, RenamedString)]
+                first: String,
+                #[as_mut([u8])]
+                second: Vec<u8>,
+            }
 
-        // 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<Vec<u8>> for Types {
-            fn as_mut(&mut self) -> &mut Vec<u8> {
-                &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<Vec<u8>> for Types {
+                fn as_mut(&mut self) -> &mut Vec<u8> {
+                    &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<T, U> {
-                first: Vec<T>,
-                second: VecDeque<U>,
-            }
-
             #[test]
             fn nothing() {
+                #[derive(AsMut)]
+                struct Nothing<T, U> {
+                    first: Vec<T>,
+                    second: VecDeque<U>,
+                }
+
                 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<T, U, V> {
-                first: Vec<T>,
-                second: VecDeque<U>,
-                #[as_mut(skip)]
-                third: V,
-            }
-
             #[test]
             fn skip() {
+                #[derive(AsMut)]
+                struct Skip<T, U, V> {
+                    first: Vec<T>,
+                    second: VecDeque<U>,
+                    #[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<T, U, V> {
-                #[as_mut]
-                first: Vec<T>,
-                #[as_mut]
-                second: VecDeque<U>,
-                third: V,
-            }
-
             #[test]
             fn field() {
+                #[derive(AsMut)]
+                struct Field<T, U, V> {
+                    #[as_mut]
+                    first: Vec<T>,
+                    #[as_mut]
+                    second: VecDeque<U>,
+                    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<T, U> {
-                #[as_mut(forward)]
-                first: T,
-                second: U,
-            }
-
             #[test]
             fn field_forward() {
+                #[derive(AsMut)]
+                struct FieldForward<T, U> {
+                    #[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<T, U> {
-                #[as_mut(str)]
-                first: T,
-                #[as_mut([u8])]
-                second: U,
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsMut)]
+                struct FieldForward<T: Some, U> {
+                    #[as_mut(forward)]
+                    first: T::Assoc,
+                    second: U,
+                }
+
+                let mut item = FieldForward::<bool, _> {
+                    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<T, U> {
+                    #[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<T, U> {
-                #[as_mut(Vec<T>, [T])]
-                first: Vec<T>,
-                #[as_mut(str)]
-                second: U,
+            #[test]
+            fn types_assoc() {
+                #[derive(AsMut)]
+                struct Types<T: Some, U: Some + ?Sized> {
+                    #[as_mut(str)]
+                    first: T::Assoc,
+                    #[as_mut([u8])]
+                    second: Vec<<U as Some>::Assoc>,
+                }
+
+                let mut item = Types::<bool, str> {
+                    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<T, U> {
+                    #[as_mut(Vec<T>, [T])]
+                    first: Vec<T>,
+                    #[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<T> {
-                #[as_mut([T])]
-                first: Vec<i32>,
-                second: T,
+            #[test]
+            fn types_with_inner_assoc() {
+                #[derive(AsMut)]
+                struct TypesWithInner<T: Some, U: Some> {
+                    #[as_mut(Vec<<T as Some>::Assoc>, [<T as Some>::Assoc])]
+                    first: Vec<<T as Some>::Assoc>,
+                    #[as_mut(str)]
+                    second: U::Assoc,
+                }
+
+                let mut item = TypesWithInner::<u8, bool> {
+                    first: vec![1i32],
+                    second: "a".to_owned(),
+                };
+
+                let rf: &mut Vec<i32> = 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<T> {
+                    #[as_mut([T])]
+                    first: Vec<i32>,
+                    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<T: Some> {
+                    #[as_mut([<T as Some>::Assoc])]
+                    first: Vec<i32>,
+                    second: T,
+                }
+
+                let mut item = FieldNonGeneric::<u8> {
+                    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 cc58d4b..39a3541 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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>(T);
-
             #[test]
             fn nothing() {
+                #[derive(AsRef)]
+                struct Nothing<T>(T);
+
                 let item = Nothing("test".to_owned());
 
                 assert!(ptr::eq(item.as_ref(), &item.0));
             }
 
-            #[derive(AsRef)]
-            #[as_ref(forward)]
-            struct Forward<T>(T);
+            #[test]
+            fn nothing_assoc() {
+                #[derive(AsRef)]
+                struct Nothing<T: Some>(T::Assoc);
+
+                let item = Nothing::<bool>("test".to_owned());
+
+                assert!(ptr::eq(item.as_ref(), &item.0));
+            }
 
             #[test]
             fn forward() {
+                #[derive(AsRef)]
+                #[as_ref(forward)]
+                struct Forward<T>(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<T>(#[as_ref] T);
+            #[test]
+            fn forward_assoc() {
+                #[derive(AsRef)]
+                #[as_ref(forward)]
+                struct Forward<T: Some>(T::Assoc);
+
+                let item = Forward::<bool>("test".to_owned());
+
+                let rf: &str = item.as_ref();
+                assert!(ptr::eq(rf, item.0.as_ref()));
+            }
 
             #[test]
             fn field() {
+                #[derive(AsRef)]
+                struct Field<T>(#[as_ref] T);
+
                 let item = Field("test".to_owned());
 
                 assert!(ptr::eq(item.as_ref(), &item.0));
             }
 
-            #[derive(AsRef)]
-            struct FieldForward<T>(#[as_ref(forward)] T);
-
             #[test]
             fn field_forward() {
+                #[derive(AsRef)]
+                struct FieldForward<T>(#[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>(T);
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsRef)]
+                struct FieldForward<T: Some>(#[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<T: AsRef<bool>> AsRef<bool> for Types<T> {
-                fn as_ref(&self) -> &bool {
-                    self.0.as_ref()
-                }
+                let item = FieldForward::<bool>("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>(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<T: AsRef<bool>> AsRef<bool> for Types<T> {
+                    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<T>)]
-            struct TypesInner<T>(Vec<T>);
+            #[test]
+            fn types_assoc() {
+                #[derive(AsRef)]
+                #[as_ref(i32, f64)]
+                struct Types<T: Some>(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<T: Some> AsRef<bool> for Types<T>
+                where
+                    T::Assoc: AsRef<bool>,
+                {
+                    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<T>)]
+                struct TypesInner<T>(Vec<T>);
+
                 let item = TypesInner(vec![1i32]);
 
                 assert!(ptr::eq(item.as_ref(), &item.0));
             }
 
-            #[derive(AsRef)]
-            struct FieldTypes<T>(#[as_ref(i32, f64)] T);
+            #[test]
+            fn types_inner_assoc() {
+                #[derive(AsRef)]
+                #[as_ref(Vec<T::Assoc>)]
+                struct TypesInner<T: Some>(Vec<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<T: AsRef<bool>> AsRef<bool> for FieldTypes<T> {
-                fn as_ref(&self) -> &bool {
-                    self.0.as_ref()
-                }
+                let item = TypesInner::<u8>(vec![1i32]);
+
+                assert!(ptr::eq(item.as_ref(), &item.0));
             }
 
             #[test]
             fn field_types() {
+                #[derive(AsRef)]
+                struct FieldTypes<T>(#[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<T: AsRef<bool>> AsRef<bool> for FieldTypes<T> {
+                    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<T>(#[as_ref(Vec<T>)] Vec<T>);
+            #[test]
+            fn field_types_assoc() {
+                #[derive(AsRef)]
+                struct FieldTypes<T: Some>(#[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<T: Some> AsRef<bool> for FieldTypes<T>
+                where
+                    T::Assoc: AsRef<bool>,
+                {
+                    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<T>(#[as_ref(Vec<T>)] Vec<T>);
+
                 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<T: Some>(
+                    #[as_ref(Vec<<T as Some>::Assoc>)] Vec<<T as Some>::Assoc>,
+                );
+
+                let item = FieldTypesInner::<u8>(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<const N: usize>(ConstParamHelper<N>);
-
             #[test]
             fn const_param() {
+                #[derive(AsRef)]
+                #[as_ref([i32])]
+                struct ConstParam<const N: usize>(ConstParamHelper<N>);
+
                 let item = ConstParam(ConstParamHelper([]));
 
                 assert!(ptr::eq(item.as_ref(), item.0.as_ref()));
             }
 
-            #[derive(AsRef)]
-            struct FieldConstParam<const N: usize>(
-                #[as_ref([i32])] ConstParamHelper<N>,
-            );
-
             #[test]
             fn field_const_param() {
+                #[derive(AsRef)]
+                struct FieldConstParam<const N: usize>(
+                    #[as_ref([i32])] ConstParamHelper<N>,
+                );
+
                 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<Helper> 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<Helper> 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<bool> 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<bool> 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<bool> 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<bool> 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<T> {
-                first: T,
-            }
-
             #[test]
             fn nothing() {
+                #[derive(AsRef)]
+                struct Nothing<T> {
+                    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<T> {
-                first: T,
+            #[test]
+            fn nothing_assoc() {
+                #[derive(AsRef)]
+                struct Nothing<T: Some> {
+                    first: <T as Some>::Assoc,
+                }
+
+                let item = Nothing::<bool> {
+                    first: "test".to_owned(),
+                };
+
+                assert!(ptr::eq(item.as_ref(), &item.first));
             }
 
             #[test]
             fn forward() {
+                #[derive(AsRef)]
+                #[as_ref(forward)]
+                struct Forward<T> {
+                    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<T> {
-                #[as_ref]
-                first: T,
+            #[test]
+            fn forward_assoc() {
+                #[derive(AsRef)]
+                #[as_ref(forward)]
+                struct Forward<T: Some> {
+                    first: T::Assoc,
+                }
+
+                let item = Forward::<bool> {
+                    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<T> {
+                    #[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<T> {
-                #[as_ref(forward)]
-                first: T,
-            }
-
             #[test]
             fn field_forward() {
+                #[derive(AsRef)]
+                struct FieldForward<T> {
+                    #[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<T> {
-                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<T: AsRef<bool>> AsRef<bool> for Types<T> {
-                fn as_ref(&self) -> &bool {
-                    self.first.as_ref()
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsRef)]
+                struct FieldForward<T: Some> {
+                    #[as_ref(forward)]
+                    first: T::Assoc,
                 }
+
+                let item = FieldForward::<bool> {
+                    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<T> {
+                    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<T: AsRef<bool>> AsRef<bool> for Types<T> {
+                    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<T>)]
-            struct TypesInner<T> {
-                first: Vec<T>,
+            #[test]
+            fn types_assoc() {
+                #[derive(AsRef)]
+                #[as_ref(i32, f64)]
+                struct Types<T: Some> {
+                    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<T: Some> AsRef<bool> for Types<T>
+                where
+                    T::Assoc: AsRef<bool>,
+                {
+                    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<T>)]
+                struct TypesInner<T> {
+                    first: Vec<T>,
+                }
+
                 let item = TypesInner { first: vec![1i32] };
 
                 assert!(ptr::eq(item.as_ref(), &item.first));
             }
 
-            #[derive(AsRef)]
-            struct FieldTypes<T> {
-                #[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<T: AsRef<bool>> AsRef<bool> for FieldTypes<T> {
-                fn as_ref(&self) -> &bool {
-                    self.first.as_ref()
+            #[test]
+            fn types_inner_assoc() {
+                #[derive(AsRef)]
+                #[as_ref(Vec<T::Assoc>)]
+                struct TypesInner<T: Some> {
+                    first: Vec<T::Assoc>,
                 }
+
+                let item = TypesInner::<u8> { first: vec![1i32] };
+
+                assert!(ptr::eq(item.as_ref(), &item.first));
             }
 
             #[test]
             fn field_types() {
+                #[derive(AsRef)]
+                struct FieldTypes<T> {
+                    #[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<T: AsRef<bool>> AsRef<bool> for FieldTypes<T> {
+                    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<T> {
-                #[as_ref(Vec<T>)]
-                first: Vec<T>,
+            #[test]
+            fn field_types_assoc() {
+                #[derive(AsRef)]
+                struct FieldTypes<T: Some> {
+                    #[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<T: Some> AsRef<bool> for FieldTypes<T>
+                where
+                    T::Assoc: AsRef<bool>,
+                {
+                    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<T> {
+                    #[as_ref(Vec<T>)]
+                    first: Vec<T>,
+                }
+
                 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<T: Some> {
+                    #[as_ref(Vec<<T as Some>::Assoc>)]
+                    first: Vec<<T as Some>::Assoc>,
+                }
+
+                let item = FieldTypesInner::<u8> { 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<const N: usize> {
-                first: ConstParamHelper<N>,
-            }
-
             #[test]
             fn const_param() {
+                #[derive(AsRef)]
+                #[as_ref([i32])]
+                struct ConstParam<const N: usize> {
+                    first: ConstParamHelper<N>,
+                }
+
                 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<const N: usize> {
-                #[as_ref([i32])]
-                first: ConstParamHelper<N>,
-            }
-
             #[test]
             fn field_const_param() {
+                #[derive(AsRef)]
+                struct FieldConstParam<const N: usize> {
+                    #[as_ref([i32])]
+                    first: ConstParamHelper<N>,
+                }
+
                 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<f64> 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<f64> 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<f64> 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<f64> 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<u8>,
-        );
+            #[derive(AsRef)]
+            struct Types(
+                #[as_ref(str, RenamedString)] String,
+                #[as_ref([u8])] Vec<u8>,
+            );
 
-        // 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<Vec<u8>> for Types {
-            fn as_ref(&self) -> &Vec<u8> {
-                &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<Vec<u8>> for Types {
+                fn as_ref(&self) -> &Vec<u8> {
+                    &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<T, U>(Vec<T>, VecDeque<U>);
-
             #[test]
             fn nothing() {
+                #[derive(AsRef)]
+                struct Nothing<T, U>(Vec<T>, VecDeque<U>);
+
                 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<T, U, V>(Vec<T>, VecDeque<U>, #[as_ref(skip)] V);
-
             #[test]
             fn skip() {
+                #[derive(AsRef)]
+                struct Skip<T, U, V>(Vec<T>, VecDeque<U>, #[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<T, U, V>(#[as_ref] Vec<T>, #[as_ref] VecDeque<U>, V);
-
             #[test]
             fn field() {
+                #[derive(AsRef)]
+                struct Field<T, U, V>(#[as_ref] Vec<T>, #[as_ref] VecDeque<U>, 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<T, U>(#[as_ref(forward)] T, U);
-
             #[test]
             fn field_forward() {
+                #[derive(AsRef)]
+                struct FieldForward<T, U>(#[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<T, U>(#[as_ref(str)] T, #[as_ref([u8])] U);
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsRef)]
+                struct FieldForward<T: Some, U>(#[as_ref(forward)] T::Assoc, U);
+
+                let item = FieldForward::<bool, _>("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<T, U>(#[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<T, U>(
-                #[as_ref(Vec<T>, [T])] Vec<T>,
-                #[as_ref(str)] U,
-            );
+            #[test]
+            fn types_assoc() {
+                #[derive(AsRef)]
+                struct Types<T: Some, U: Some + ?Sized>(
+                    #[as_ref(str)] <T as Some>::Assoc,
+                    #[as_ref([u8])] Vec<U::Assoc>,
+                );
+
+                let item = Types::<bool, str>("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<T, U>(
+                    #[as_ref(Vec<T>, [T])] Vec<T>,
+                    #[as_ref(str)] U,
+                );
+
                 let item = TypesWithInner(vec![1i32], "a".to_owned());
 
                 let rf: &Vec<i32> = item.as_ref();
@@ -1092,15 +1387,45 @@ mod multi_field {
                 assert!(ptr::eq(rf, item.1.as_ref()));
             }
 
-            #[derive(AsRef)]
-            struct FieldNonGeneric<T>(#[as_ref([T])] Vec<i32>, T);
+            #[test]
+            fn types_with_inner_assoc() {
+                #[derive(AsRef)]
+                struct TypesWithInner<T: Some, U: Some>(
+                    #[as_ref(Vec<T::Assoc>, [T::Assoc])] Vec<T::Assoc>,
+                    #[as_ref(str)] U::Assoc,
+                );
+
+                let item = TypesWithInner::<u8, bool>(vec![1i32], "a".to_owned());
+
+                let rf: &Vec<i32> = 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<T>(#[as_ref([T])] Vec<i32>, 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<T: Some>(#[as_ref([T::Assoc])] Vec<i32>, T);
+
+                let item = FieldNonGeneric::<u8>(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<f64> 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<f64> 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<f64> 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<f64> 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<u8>,
-        }
+            #[derive(AsRef)]
+            struct Types {
+                #[as_ref(str, RenamedString)]
+                first: String,
+                #[as_ref([u8])]
+                second: Vec<u8>,
+            }
 
-        // 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<Vec<u8>> for Types {
-            fn as_ref(&self) -> &Vec<u8> {
-                &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<Vec<u8>> for Types {
+                fn as_ref(&self) -> &Vec<u8> {
+                    &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<T, U> {
-                first: Vec<T>,
-                second: VecDeque<U>,
-            }
-
             #[test]
             fn nothing() {
+                #[derive(AsRef)]
+                struct Nothing<T, U> {
+                    first: Vec<T>,
+                    second: VecDeque<U>,
+                }
+
                 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<T, U, V> {
-                first: Vec<T>,
-                second: VecDeque<U>,
-                #[as_ref(skip)]
-                third: V,
-            }
-
             #[test]
             fn skip() {
+                #[derive(AsRef)]
+                struct Skip<T, U, V> {
+                    first: Vec<T>,
+                    second: VecDeque<U>,
+                    #[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<T, U, V> {
-                #[as_ref]
-                first: Vec<T>,
-                #[as_ref]
-                second: VecDeque<U>,
-                third: V,
-            }
-
             #[test]
             fn field() {
+                #[derive(AsRef)]
+                struct Field<T, U, V> {
+                    #[as_ref]
+                    first: Vec<T>,
+                    #[as_ref]
+                    second: VecDeque<U>,
+                    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<T, U> {
-                #[as_ref(forward)]
-                first: T,
-                second: U,
-            }
-
             #[test]
             fn field_forward() {
+                #[derive(AsRef)]
+                struct FieldForward<T, U> {
+                    #[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<T, U> {
-                #[as_ref(str)]
-                first: T,
-                #[as_ref([u8])]
-                second: U,
+            #[test]
+            fn field_forward_assoc() {
+                #[derive(AsRef)]
+                struct FieldForward<T: Some, U> {
+                    #[as_ref(forward)]
+                    first: T::Assoc,
+                    second: U,
+                }
+
+                let item = FieldForward::<bool, _> {
+                    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<T, U> {
+                    #[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<T, U> {
-                #[as_ref(Vec<T>, [T])]
-                first: Vec<T>,
-                #[as_ref(str)]
-                second: U,
+            #[test]
+            fn types_assoc() {
+                #[derive(AsRef)]
+                struct Types<T: Some, U: Some + ?Sized> {
+                    #[as_ref(str)]
+                    first: T::Assoc,
+                    #[as_ref([u8])]
+                    second: Vec<<U as Some>::Assoc>,
+                }
+
+                let item = Types::<bool, str> {
+                    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<T, U> {
+                    #[as_ref(Vec<T>, [T])]
+                    first: Vec<T>,
+                    #[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<T> {
-                #[as_ref([T])]
-                first: Vec<i32>,
-                second: T,
+            #[test]
+            fn types_with_inner_assoc() {
+                #[derive(AsRef)]
+                struct TypesWithInner<T: Some, U: Some> {
+                    #[as_ref(Vec<<T as Some>::Assoc>, [<T as Some>::Assoc])]
+                    first: Vec<<T as Some>::Assoc>,
+                    #[as_ref(str)]
+                    second: U::Assoc,
+                }
+
+                let item = TypesWithInner::<u8, bool> {
+                    first: vec![1i32],
+                    second: "a".to_owned(),
+                };
+
+                let rf: &Vec<i32> = 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<T> {
+                    #[as_ref([T])]
+                    first: Vec<i32>,
+                    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<T: Some> {
+                    #[as_ref([<T as Some>::Assoc])]
+                    first: Vec<i32>,
+                    second: T,
+                }
+
+                let item = FieldNonGeneric::<u8> {
+                    first: vec![],
+                    second: 2u8,
+                };
+
+                assert!(ptr::eq(item.as_ref(), item.first.as_ref()));
+            }
         }
 
         #[cfg(nightly)]