diff --git a/src/internals/attributes/field/snapshots/bounds_parsing1-2.snap b/src/internals/attributes/field/snapshots/bounds_parsing1-2.snap
new file mode 100644
index 0000000..e14b67a
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing1-2.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(attrs.deserialize)
+snapshot_kind: text
+---
+K : Hash + Ord
+V : Eq + Ord
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing1.snap b/src/internals/attributes/field/snapshots/bounds_parsing1.snap
new file mode 100644
index 0000000..9c0ea2b
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing1.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(attrs.serialize.clone())
+snapshot_kind: text
+---
+K : Hash + Eq + Ord
+V : Ord
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing2-2.snap b/src/internals/attributes/field/snapshots/bounds_parsing2-2.snap
new file mode 100644
index 0000000..db66449
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing2-2.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(attrs.deserialize)
+snapshot_kind: text
+---
+K : Hash + Eq + borsh :: de :: BorshDeserialize
+V : borsh :: de :: BorshDeserialize
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing2.snap b/src/internals/attributes/field/snapshots/bounds_parsing2.snap
new file mode 100644
index 0000000..a0ab777
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing2.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(attrs.serialize.clone())
+snapshot_kind: text
+---
+K : Hash + Eq + borsh :: ser :: BorshSerialize
+V : borsh :: ser :: BorshSerialize
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing3.snap b/src/internals/attributes/field/snapshots/bounds_parsing3.snap
new file mode 100644
index 0000000..db66449
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing3.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(attrs.deserialize)
+snapshot_kind: text
+---
+K : Hash + Eq + borsh :: de :: BorshDeserialize
+V : borsh :: de :: BorshDeserialize
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing4.snap b/src/internals/attributes/field/snapshots/bounds_parsing4.snap
new file mode 100644
index 0000000..95fbd12
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing4.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(attrs.deserialize)
+snapshot_kind: text
+---
+K : Hash
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing_error.snap b/src/internals/attributes/field/snapshots/bounds_parsing_error.snap
new file mode 100644
index 0000000..320eb4d
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing_error.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "malformed bound attribute, expected `bound(deserialize = ..., serialize = ...)`",
+)
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing_error2.snap b/src/internals/attributes/field/snapshots/bounds_parsing_error2.snap
new file mode 100644
index 0000000..11e8cd0
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing_error2.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "expected `:`",
+)
diff --git a/src/internals/attributes/field/snapshots/bounds_parsing_error3.snap b/src/internals/attributes/field/snapshots/bounds_parsing_error3.snap
new file mode 100644
index 0000000..bea222e
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/bounds_parsing_error3.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "expected borsh bound attribute to be a string: `deserialize = \"...\"`",
+)
diff --git a/src/internals/attributes/field/snapshots/reject_multiple_borsh_attrs.snap b/src/internals/attributes/field/snapshots/reject_multiple_borsh_attrs.snap
new file mode 100644
index 0000000..c62cede
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/reject_multiple_borsh_attrs.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "multiple `borsh` attributes not allowed",
+)
diff --git a/src/internals/attributes/field/snapshots/root_bounds_and_params_combined-2.snap b/src/internals/attributes/field/snapshots/root_bounds_and_params_combined-2.snap
new file mode 100644
index 0000000..a55c49f
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/root_bounds_and_params_combined-2.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(schema.params.clone())
+snapshot_kind: text
+---
+T => < T as TraitName > :: Associated
+V => Vec < V >
diff --git a/src/internals/attributes/field/snapshots/root_bounds_and_params_combined-3.snap b/src/internals/attributes/field/snapshots/root_bounds_and_params_combined-3.snap
new file mode 100644
index 0000000..8f44a0b
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/root_bounds_and_params_combined-3.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_tokenizable(attrs.serialize_with)
+snapshot_kind: text
+---
+third_party_impl :: serialize_third_party
diff --git a/src/internals/attributes/field/snapshots/root_bounds_and_params_combined.snap b/src/internals/attributes/field/snapshots/root_bounds_and_params_combined.snap
new file mode 100644
index 0000000..83c29e7
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/root_bounds_and_params_combined.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(bounds.deserialize)
+snapshot_kind: text
+---
+K : Hash
diff --git a/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap b/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap
new file mode 100644
index 0000000..817942d
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "malformed borsh attribute, expected `borsh(bound(...), deserialize_with = ..., schema(...), serialize_with = ..., skip)`",
+)
diff --git a/src/internals/attributes/field/snapshots/root_error.snap b/src/internals/attributes/field/snapshots/root_error.snap
new file mode 100644
index 0000000..817942d
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/root_error.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "malformed borsh attribute, expected `borsh(bound(...), deserialize_with = ..., schema(...), serialize_with = ..., skip)`",
+)
diff --git a/src/internals/attributes/field/snapshots/schema_params_parsing1.snap b/src/internals/attributes/field/snapshots/schema_params_parsing1.snap
new file mode 100644
index 0000000..31e5804
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_params_parsing1.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(schema_attrs.unwrap().params)
+snapshot_kind: text
+---
+T => < T as TraitName > :: Associated
diff --git a/src/internals/attributes/field/snapshots/schema_params_parsing2.snap b/src/internals/attributes/field/snapshots/schema_params_parsing2.snap
new file mode 100644
index 0000000..06d57ef
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_params_parsing2.snap
@@ -0,0 +1,7 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_vec_of_tokenizable(schema_attrs.unwrap().params)
+snapshot_kind: text
+---
+T => < T as TraitName > :: Associated
+V => Vec < V >
diff --git a/src/internals/attributes/field/snapshots/schema_params_parsing_error.snap b/src/internals/attributes/field/snapshots/schema_params_parsing_error.snap
new file mode 100644
index 0000000..55197be
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_params_parsing_error.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "expected `>`",
+)
diff --git a/src/internals/attributes/field/snapshots/schema_params_parsing_error2.snap b/src/internals/attributes/field/snapshots/schema_params_parsing_error2.snap
new file mode 100644
index 0000000..5fa6137
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_params_parsing_error2.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "malformed schema attribute, expected `schema(params = ..., with_funcs(...))`",
+)
diff --git a/src/internals/attributes/field/snapshots/schema_with_funcs_parsing-2.snap b/src/internals/attributes/field/snapshots/schema_with_funcs_parsing-2.snap
new file mode 100644
index 0000000..0c35ef9
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_with_funcs_parsing-2.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_tokenizable(with_funcs.definitions)
+snapshot_kind: text
+---
+third_party_impl :: add_definitions_recursively :: < K , V >
diff --git a/src/internals/attributes/field/snapshots/schema_with_funcs_parsing.snap b/src/internals/attributes/field/snapshots/schema_with_funcs_parsing.snap
new file mode 100644
index 0000000..69d523c
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_with_funcs_parsing.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_tokenizable(with_funcs.declaration.clone())
+snapshot_kind: text
+---
+third_party_impl :: declaration :: < K , V >
diff --git a/src/internals/attributes/field/snapshots/schema_with_funcs_parsing_error.snap b/src/internals/attributes/field/snapshots/schema_with_funcs_parsing_error.snap
new file mode 100644
index 0000000..7826629
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/schema_with_funcs_parsing_error.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "both `declaration = ...` and `definitions = ...` have to be specified at the same time",
+)
diff --git a/src/internals/attributes/field/snapshots/ser_de_with_parsing1-2.snap b/src/internals/attributes/field/snapshots/ser_de_with_parsing1-2.snap
new file mode 100644
index 0000000..da145df
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/ser_de_with_parsing1-2.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_tokenizable(attrs.deserialize_with)
+snapshot_kind: text
+---
+third_party_impl :: deserialize_third_party
diff --git a/src/internals/attributes/field/snapshots/ser_de_with_parsing1.snap b/src/internals/attributes/field/snapshots/ser_de_with_parsing1.snap
new file mode 100644
index 0000000..1df2e2f
--- /dev/null
+++ b/src/internals/attributes/field/snapshots/ser_de_with_parsing1.snap
@@ -0,0 +1,6 @@
+---
+source: src/internals/attributes/field/mod.rs
+expression: debug_print_tokenizable(attrs.serialize_with.as_ref())
+snapshot_kind: text
+---
+third_party_impl :: serialize_third_party
diff --git a/src/internals/attributes/item/snapshots/check_attrs_borsh_invalid_on_whole_item.snap b/src/internals/attributes/item/snapshots/check_attrs_borsh_invalid_on_whole_item.snap
new file mode 100644
index 0000000..cba39f6
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/check_attrs_borsh_invalid_on_whole_item.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`crate`, `use_discriminant` or `init` are the only supported attributes for `borsh`",
+)
diff --git a/src/internals/attributes/item/snapshots/check_attrs_borsh_skip_on_whole_item.snap b/src/internals/attributes/item/snapshots/check_attrs_borsh_skip_on_whole_item.snap
new file mode 100644
index 0000000..cba39f6
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/check_attrs_borsh_skip_on_whole_item.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`crate`, `use_discriminant` or `init` are the only supported attributes for `borsh`",
+)
diff --git a/src/internals/attributes/item/snapshots/check_attrs_init_function_wrong_format.snap b/src/internals/attributes/item/snapshots/check_attrs_init_function_wrong_format.snap
new file mode 100644
index 0000000..cba39f6
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/check_attrs_init_function_wrong_format.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`crate`, `use_discriminant` or `init` are the only supported attributes for `borsh`",
+)
diff --git a/src/internals/attributes/item/snapshots/check_attrs_use_discriminant_on_struct.snap b/src/internals/attributes/item/snapshots/check_attrs_use_discriminant_on_struct.snap
new file mode 100644
index 0000000..673924e
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/check_attrs_use_discriminant_on_struct.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "borsh(use_discriminant=<bool>) does not support structs",
+)
diff --git a/src/internals/attributes/item/snapshots/init_function_parsing_error.snap b/src/internals/attributes/item/snapshots/init_function_parsing_error.snap
new file mode 100644
index 0000000..ecd2cc4
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/init_function_parsing_error.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "expected identifier",
+)
diff --git a/src/internals/attributes/item/snapshots/reject_multiple_borsh_attrs.snap b/src/internals/attributes/item/snapshots/reject_multiple_borsh_attrs.snap
new file mode 100644
index 0000000..48c4454
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/reject_multiple_borsh_attrs.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "multiple `borsh` attributes not allowed",
+)
diff --git a/src/internals/attributes/item/snapshots/use_discriminant_wrong_value.snap b/src/internals/attributes/item/snapshots/use_discriminant_wrong_value.snap
new file mode 100644
index 0000000..18cc541
--- /dev/null
+++ b/src/internals/attributes/item/snapshots/use_discriminant_wrong_value.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/attributes/item/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "`use_discriminant` accepts only `true` or `false`",
+)
diff --git a/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap b/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap
new file mode 100644
index 0000000..4cc6941
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap
@@ -0,0 +1,43 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for X {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl borsh::de::EnumExt for X {
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            X::A
+        } else if variant_tag == 1u8 {
+            X::B
+        } else if variant_tag == 2u8 {
+            X::C
+        } else if variant_tag == 3u8 {
+            X::D
+        } else if variant_tag == 4u8 {
+            X::E
+        } else if variant_tag == 5u8 {
+            X::F
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap b/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap
new file mode 100644
index 0000000..0290d9d
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap
@@ -0,0 +1,43 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for X {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl borsh::de::EnumExt for X {
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0 {
+            X::A
+        } else if variant_tag == 20 {
+            X::B
+        } else if variant_tag == 20 + 1 {
+            X::C
+        } else if variant_tag == 20 + 1 + 1 {
+            X::D
+        } else if variant_tag == 10 {
+            X::E
+        } else if variant_tag == 10 + 1 {
+            X::F
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/borsh_init_func.snap b/src/internals/deserialize/enums/snapshots/borsh_init_func.snap
new file mode 100644
index 0000000..30ca391
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/borsh_init_func.snap
@@ -0,0 +1,44 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for A {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl borsh::de::EnumExt for A {
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::A
+        } else if variant_tag == 1u8 {
+            A::B
+        } else if variant_tag == 2u8 {
+            A::C
+        } else if variant_tag == 3u8 {
+            A::D
+        } else if variant_tag == 4u8 {
+            A::E
+        } else if variant_tag == 5u8 {
+            A::F
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        return_value.initialization_method();
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap b/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap
new file mode 100644
index 0000000..9ea00fc
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap
@@ -0,0 +1,40 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for AA {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl borsh::de::EnumExt for AA {
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            AA::B {
+                c: core::default::Default::default(),
+                d: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            AA::NegatedVariant {
+                beta: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap b/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap
new file mode 100644
index 0000000..853aa6a
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap
@@ -0,0 +1,40 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for AAT {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl borsh::de::EnumExt for AAT {
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            AAT::B(
+                core::default::Default::default(),
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else if variant_tag == 1u8 {
+            AAT::NegatedVariant {
+                beta: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/bound_generics.snap b/src/internals/deserialize/enums/snapshots/bound_generics.snap
new file mode 100644
index 0000000..036a29a
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/bound_generics.snap
@@ -0,0 +1,53 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V, U> borsh::de::BorshDeserialize for A<K, V, U>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<K: Key, V, U> borsh::de::EnumExt for A<K, V, U>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::B {
+                x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+                y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::C(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap b/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap
new file mode 100644
index 0000000..aed72fc
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap
@@ -0,0 +1,49 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Ord, V> borsh::de::BorshDeserialize for C<K, V>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<K: Ord, V> borsh::de::EnumExt for C<K, V>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            C::C3(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else if variant_tag == 1u8 {
+            C::C4 {
+                x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+                y: third_party_impl::deserialize_third_party(reader)?,
+            }
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap b/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap
new file mode 100644
index 0000000..a5ecf13
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap
@@ -0,0 +1,55 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V, U> borsh::de::BorshDeserialize for A<K, V, U>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+    K: core::default::Default,
+    V: core::default::Default,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<K: Key, V, U> borsh::de::EnumExt for A<K, V, U>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+    K: core::default::Default,
+    V: core::default::Default,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::B {
+                x: core::default::Default::default(),
+                y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::C(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap b/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap
new file mode 100644
index 0000000..4e25f92
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap
@@ -0,0 +1,53 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V, U> borsh::de::BorshDeserialize for A<K, V, U>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: core::default::Default,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<K: Key, V, U> borsh::de::EnumExt for A<K, V, U>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: core::default::Default,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::B {
+                x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+                y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::C(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                core::default::Default::default(),
+            )
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap b/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap
new file mode 100644
index 0000000..046fe80
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap
@@ -0,0 +1,49 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T: Debug, U> borsh::de::BorshDeserialize for A<T, U>
+where
+    T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<T: Debug, U> borsh::de::EnumExt for A<T, U>
+where
+    T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::C {
+                a: borsh::BorshDeserialize::deserialize_reader(reader)?,
+                b: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::D(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/recursive_enum.snap b/src/internals/deserialize/enums/snapshots/recursive_enum.snap
new file mode 100644
index 0000000..e96b707
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/recursive_enum.snap
@@ -0,0 +1,51 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V> borsh::de::BorshDeserialize for A<K, V>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<K: Key, V> borsh::de::EnumExt for A<K, V>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::B {
+                x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+                y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::C(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap b/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap
new file mode 100644
index 0000000..9c688c2
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap
@@ -0,0 +1,43 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl reexporter::borsh::de::BorshDeserialize for A {
+    fn deserialize_reader<__R: reexporter::borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, reexporter::borsh::io::Error> {
+        let tag = <u8 as reexporter::borsh::de::BorshDeserialize>::deserialize_reader(
+            reader,
+        )?;
+        <Self as reexporter::borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl reexporter::borsh::de::EnumExt for A {
+    fn deserialize_variant<__R: reexporter::borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, reexporter::borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::B {
+                x: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?,
+                y: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::C(
+                reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?,
+                reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else {
+            return Err(
+                reexporter::borsh::io::Error::new(
+                    reexporter::borsh::io::ErrorKind::InvalidData,
+                    reexporter::borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/enums/snapshots/simple_generics.snap b/src/internals/deserialize/enums/snapshots/simple_generics.snap
new file mode 100644
index 0000000..e33be6d
--- /dev/null
+++ b/src/internals/deserialize/enums/snapshots/simple_generics.snap
@@ -0,0 +1,51 @@
+---
+source: src/internals/deserialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::de::BorshDeserialize for A<K, V, U>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let tag = <u8 as borsh::de::BorshDeserialize>::deserialize_reader(reader)?;
+        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
+    }
+}
+impl<K, V, U> borsh::de::EnumExt for A<K, V, U>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_variant<__R: borsh::io::Read>(
+        reader: &mut __R,
+        variant_tag: u8,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = if variant_tag == 0u8 {
+            A::B {
+                x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+                y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            }
+        } else if variant_tag == 1u8 {
+            A::C(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            )
+        } else {
+            return Err(
+                borsh::io::Error::new(
+                    borsh::io::ErrorKind::InvalidData,
+                    borsh::__private::maybestd::format!(
+                        "Unexpected variant tag: {:?}", variant_tag
+                    ),
+                ),
+            )
+        };
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/borsh_init_func.snap b/src/internals/deserialize/structs/snapshots/borsh_init_func.snap
new file mode 100644
index 0000000..4e5a360
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/borsh_init_func.snap
@@ -0,0 +1,17 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for A {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        let mut return_value = Self {
+            x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        };
+        return_value.initialization_method();
+        Ok(return_value)
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/bound_generics.snap b/src/internals/deserialize/structs/snapshots/bound_generics.snap
new file mode 100644
index 0000000..09e1467
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/bound_generics.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V> borsh::de::BorshDeserialize for A<K, V>
+where
+    V: Value,
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap b/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap
new file mode 100644
index 0000000..921925a
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap
@@ -0,0 +1,19 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Ord, V> borsh::de::BorshDeserialize for A<K, V>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            x: third_party_impl::deserialize_third_party(reader)?,
+            y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap b/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap
new file mode 100644
index 0000000..dd2f4c0
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap
@@ -0,0 +1,19 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T: Debug, U> borsh::de::BorshDeserialize for C<T, U>
+where
+    T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize,
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            a: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            b: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap b/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap
new file mode 100644
index 0000000..52fab9b
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::de::BorshDeserialize for G<K, V, U>
+where
+    U: borsh::de::BorshDeserialize,
+    K: core::default::Default,
+    V: core::default::Default,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            x: core::default::Default::default(),
+            y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap b/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap
new file mode 100644
index 0000000..14595af
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap
@@ -0,0 +1,22 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::de::BorshDeserialize for G<K, V, U>
+where
+    U: borsh::de::BorshDeserialize,
+    K: core::default::Default,
+    V: core::default::Default,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(
+            Self(
+                core::default::Default::default(),
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            ),
+        )
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap b/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap
new file mode 100644
index 0000000..3489520
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap
@@ -0,0 +1,22 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::de::BorshDeserialize for G<K, V, U>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+    U: core::default::Default,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(
+            Self(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                core::default::Default::default(),
+            ),
+        )
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap b/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap
new file mode 100644
index 0000000..ad69d43
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::de::BorshDeserialize for G1<K, V, U>
+where
+    U: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(
+            Self(
+                core::default::Default::default(),
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            ),
+        )
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/recursive_struct.snap b/src/internals/deserialize/structs/snapshots/recursive_struct.snap
new file mode 100644
index 0000000..4c3e18c
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/recursive_struct.snap
@@ -0,0 +1,15 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for CRecC {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            a: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            b: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap b/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap
new file mode 100644
index 0000000..c721c17
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T> borsh::de::BorshDeserialize for TupleA<T>
+where
+    T: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(
+            Self(
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+                borsh::BorshDeserialize::deserialize_reader(reader)?,
+            ),
+        )
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/simple_generics.snap b/src/internals/deserialize/structs/snapshots/simple_generics.snap
new file mode 100644
index 0000000..978ac7e
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/simple_generics.snap
@@ -0,0 +1,19 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::de::BorshDeserialize for A<K, V>
+where
+    K: borsh::de::BorshDeserialize,
+    V: borsh::de::BorshDeserialize,
+{
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/simple_struct.snap b/src/internals/deserialize/structs/snapshots/simple_struct.snap
new file mode 100644
index 0000000..140cb95
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/simple_struct.snap
@@ -0,0 +1,15 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::de::BorshDeserialize for A {
+    fn deserialize_reader<__R: borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, borsh::io::Error> {
+        Ok(Self {
+            x: borsh::BorshDeserialize::deserialize_reader(reader)?,
+            y: borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap b/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap
new file mode 100644
index 0000000..496af28
--- /dev/null
+++ b/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap
@@ -0,0 +1,15 @@
+---
+source: src/internals/deserialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl reexporter::borsh::de::BorshDeserialize for A {
+    fn deserialize_reader<__R: reexporter::borsh::io::Read>(
+        reader: &mut __R,
+    ) -> ::core::result::Result<Self, reexporter::borsh::io::Error> {
+        Ok(Self {
+            x: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?,
+            y: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?,
+        })
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap b/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap
new file mode 100644
index 0000000..62721fd
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap
@@ -0,0 +1,65 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for X {
+    fn declaration() -> borsh::schema::Declaration {
+        "X".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XA;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XB;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XC;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XD;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XE;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XF;
+        <XA as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XB as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XC as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XD as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XE as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XF as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "A".into(), < XA as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "B".into(), < XB as
+                borsh::BorshSchema > ::declaration()), (u8::from(2u8) as i64, "C".into(),
+                < XC as borsh::BorshSchema > ::declaration()), (u8::from(3u8) as i64, "D"
+                .into(), < XD as borsh::BorshSchema > ::declaration()), (u8::from(4u8) as
+                i64, "E".into(), < XE as borsh::BorshSchema > ::declaration()),
+                (u8::from(5u8) as i64, "F".into(), < XF as borsh::BorshSchema >
+                ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap b/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap
new file mode 100644
index 0000000..9f794e1
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap
@@ -0,0 +1,65 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for X {
+    fn declaration() -> borsh::schema::Declaration {
+        "X".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XA;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XB;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XC;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XD;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XE;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct XF;
+        <XA as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XB as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XC as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XD as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XE as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <XF as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0) as i64, "A".into(), < XA as borsh::BorshSchema >
+                ::declaration()), (u8::from(20) as i64, "B".into(), < XB as
+                borsh::BorshSchema > ::declaration()), (u8::from(20 + 1) as i64, "C"
+                .into(), < XC as borsh::BorshSchema > ::declaration()), (u8::from(20 + 1
+                + 1) as i64, "D".into(), < XD as borsh::BorshSchema > ::declaration()),
+                (u8::from(10) as i64, "E".into(), < XE as borsh::BorshSchema >
+                ::declaration()), (u8::from(10 + 1) as i64, "F".into(), < XF as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/check_with_funcs_skip_conflict.snap b/src/internals/schema/enums/snapshots/check_with_funcs_skip_conflict.snap
new file mode 100644
index 0000000..5ea8df9
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/check_with_funcs_skip_conflict.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`skip` cannot be used at the same time as `schema(with_funcs(...))`",
+)
diff --git a/src/internals/schema/enums/snapshots/complex_enum.snap b/src/internals/schema/enums/snapshots/complex_enum.snap
new file mode 100644
index 0000000..425d51a
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/complex_enum.snap
@@ -0,0 +1,56 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ABacon;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AEggs;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASalad(Tomatoes, Cucumber, Oil);
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASausage {
+            wrapper: Wrapper,
+            filling: Filling,
+        }
+        <ABacon as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <AEggs as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASalad as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASausage as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "Eggs".into(), < AEggs as
+                borsh::BorshSchema > ::declaration()), (u8::from(2u8) as i64, "Salad"
+                .into(), < ASalad as borsh::BorshSchema > ::declaration()),
+                (u8::from(3u8) as i64, "Sausage".into(), < ASausage as borsh::BorshSchema
+                > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/complex_enum_generics.snap b/src/internals/schema/enums/snapshots/complex_enum_generics.snap
new file mode 100644
index 0000000..450c767
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/complex_enum_generics.snap
@@ -0,0 +1,64 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<C, W> borsh::BorshSchema for A<C, W>
+where
+    C: borsh::BorshSchema,
+    W: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < C as borsh::BorshSchema > ::declaration(), < W as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ABacon;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AEggs;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASalad<C>(Tomatoes, C, Oil);
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASausage<W> {
+            wrapper: W,
+            filling: Filling,
+        }
+        <ABacon as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <AEggs as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASalad<C> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASausage<W> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "Eggs".into(), < AEggs as
+                borsh::BorshSchema > ::declaration()), (u8::from(2u8) as i64, "Salad"
+                .into(), < ASalad < C > as borsh::BorshSchema > ::declaration()),
+                (u8::from(3u8) as i64, "Sausage".into(), < ASausage < W > as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap b/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap
new file mode 100644
index 0000000..5a4e0a7
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap
@@ -0,0 +1,66 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<W, U, C> borsh::BorshSchema for A<W, U, C>
+where
+    U: borsh::BorshSchema,
+    C: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < U as borsh::BorshSchema > ::declaration(), < C as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ABacon;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AEggs;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASalad<C>(Tomatoes, C, Oil);
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASausage<W, U> {
+            #[borsh(skip)]
+            wrapper: W,
+            filling: Filling,
+            unexpected: U,
+        }
+        <ABacon as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <AEggs as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASalad<C> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASausage<W, U> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "Eggs".into(), < AEggs as
+                borsh::BorshSchema > ::declaration()), (u8::from(2u8) as i64, "Salad"
+                .into(), < ASalad < C > as borsh::BorshSchema > ::declaration()),
+                (u8::from(3u8) as i64, "Sausage".into(), < ASausage < W, U > as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap b/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap
new file mode 100644
index 0000000..372e187
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap
@@ -0,0 +1,66 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<C: Eq, W> borsh::BorshSchema for A<C, W>
+where
+    W: Hash,
+    W: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < W as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ABacon;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AEggs;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASalad<C: Eq>(Tomatoes, #[borsh(skip)] C, Oil);
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ASausage<W>
+        where
+            W: Hash,
+        {
+            wrapper: W,
+            filling: Filling,
+        }
+        <ABacon as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <AEggs as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASalad<C> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ASausage<W> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "Eggs".into(), < AEggs as
+                borsh::BorshSchema > ::declaration()), (u8::from(2u8) as i64, "Salad"
+                .into(), < ASalad < C > as borsh::BorshSchema > ::declaration()),
+                (u8::from(3u8) as i64, "Sausage".into(), < ASausage < W > as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap b/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap
new file mode 100644
index 0000000..e4f4b72
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap
@@ -0,0 +1,47 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AB {
+            c: i32,
+            #[borsh(skip)]
+            d: u32,
+            l: u64,
+        }
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ANegative {
+            beta: String,
+        }
+        <AB as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <ANegative as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "B".into(), < AB as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "Negative".into(), < ANegative
+                as borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/generic_associated_type.snap b/src/internals/schema/enums/snapshots/generic_associated_type.snap
new file mode 100644
index 0000000..9edf075
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/generic_associated_type.snap
@@ -0,0 +1,74 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T, K, V> borsh::BorshSchema for EnumParametrized<T, K, V>
+where
+    K: TraitName,
+    K: core::cmp::Ord,
+    V: core::cmp::Ord,
+    T: Eq + Hash,
+    T: borsh::BorshSchema,
+    K: borsh::BorshSchema,
+    K::Associated: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < T as borsh::BorshSchema > ::declaration(), < K as borsh::BorshSchema >
+            ::declaration(), < K::Associated as borsh::BorshSchema > ::declaration(), < V
+            as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "EnumParametrized", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct EnumParametrizedB<K, V>
+        where
+            K: TraitName,
+            K: core::cmp::Ord,
+            V: core::cmp::Ord,
+        {
+            x: BTreeMap<K, V>,
+            y: String,
+            z: K::Associated,
+        }
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct EnumParametrizedC<T>(
+            T,
+            u16,
+        )
+        where
+            T: Eq + Hash;
+        <EnumParametrizedB<
+            K,
+            V,
+        > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <EnumParametrizedC<
+            T,
+        > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "B".into(), < EnumParametrizedB < K, V > as
+                borsh::BorshSchema > ::declaration()), (u8::from(1u8) as i64, "C".into(),
+                < EnumParametrizedC < T > as borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap b/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap
new file mode 100644
index 0000000..a17b83e
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap
@@ -0,0 +1,75 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T, K, V> borsh::BorshSchema for EnumParametrized<T, K, V>
+where
+    K: TraitName,
+    K: core::cmp::Ord,
+    V: core::cmp::Ord,
+    T: Eq + Hash,
+    T: borsh::BorshSchema,
+    K: borsh::BorshSchema,
+    <K as TraitName>::Associated: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < T as borsh::BorshSchema > ::declaration(), < K as borsh::BorshSchema >
+            ::declaration(), < < K as TraitName > ::Associated as borsh::BorshSchema >
+            ::declaration(), < V as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "EnumParametrized", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct EnumParametrizedB<K, V>
+        where
+            K: TraitName,
+            K: core::cmp::Ord,
+            V: core::cmp::Ord,
+        {
+            x: BTreeMap<K, V>,
+            y: String,
+            #[borsh(schema(params = "K => <K as TraitName>::Associated"))]
+            z: <K as TraitName>::Associated,
+        }
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct EnumParametrizedC<T>(
+            T,
+            u16,
+        )
+        where
+            T: Eq + Hash;
+        <EnumParametrizedB<
+            K,
+            V,
+        > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <EnumParametrizedC<
+            T,
+        > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "B".into(), < EnumParametrizedB < K, V > as
+                borsh::BorshSchema > ::declaration()), (u8::from(1u8) as i64, "C".into(),
+                < EnumParametrizedC < T > as borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/generic_associated_type_param_override_conflict.snap b/src/internals/schema/enums/snapshots/generic_associated_type_param_override_conflict.snap
new file mode 100644
index 0000000..d850a03
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/generic_associated_type_param_override_conflict.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`skip` cannot be used at the same time as `schema(params = ...)`",
+)
diff --git a/src/internals/schema/enums/snapshots/recursive_enum.snap b/src/internals/schema/enums/snapshots/recursive_enum.snap
new file mode 100644
index 0000000..87ae828
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/recursive_enum.snap
@@ -0,0 +1,55 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V> borsh::BorshSchema for A<K, V>
+where
+    V: Value,
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AB<K: Key, V>
+        where
+            V: Value,
+        {
+            x: HashMap<K, V>,
+            y: String,
+        }
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AC<K: Key>(K, Vec<A>);
+        <AB<K, V> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <AC<K> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "B".into(), < AB < K, V > as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "C".into(), < AC < K > as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/simple_enum.snap b/src/internals/schema/enums/snapshots/simple_enum.snap
new file mode 100644
index 0000000..6f5b10b
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/simple_enum.snap
@@ -0,0 +1,40 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ABacon;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct AEggs;
+        <ABacon as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <AEggs as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "Eggs".into(), < AEggs as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap b/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap
new file mode 100644
index 0000000..7bf5a1c
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap
@@ -0,0 +1,45 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl reexporter::borsh::BorshSchema for A {
+    fn declaration() -> reexporter::borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut reexporter::borsh::__private::maybestd::collections::BTreeMap<
+            reexporter::borsh::schema::Declaration,
+            reexporter::borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(reexporter::borsh::BorshSchema)]
+        #[borsh(crate = "reexporter :: borsh")]
+        struct ABacon;
+        #[allow(dead_code)]
+        #[derive(reexporter::borsh::BorshSchema)]
+        #[borsh(crate = "reexporter :: borsh")]
+        struct AEggs;
+        <ABacon as reexporter::borsh::BorshSchema>::add_definitions_recursively(
+            definitions,
+        );
+        <AEggs as reexporter::borsh::BorshSchema>::add_definitions_recursively(
+            definitions,
+        );
+        let definition = reexporter::borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: reexporter::borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as
+                reexporter::borsh::BorshSchema > ::declaration()), (u8::from(1u8) as i64,
+                "Eggs".into(), < AEggs as reexporter::borsh::BorshSchema >
+                ::declaration())
+            ],
+        };
+        reexporter::borsh::schema::add_definition(
+            <Self as reexporter::borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/single_field_enum.snap b/src/internals/schema/enums/snapshots/single_field_enum.snap
new file mode 100644
index 0000000..dc2b33f
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/single_field_enum.snap
@@ -0,0 +1,34 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct ABacon;
+        <ABacon as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Bacon".into(), < ABacon as borsh::BorshSchema >
+                ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/trailing_comma_generics.snap b/src/internals/schema/enums/snapshots/trailing_comma_generics.snap
new file mode 100644
index 0000000..ce20112
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/trailing_comma_generics.snap
@@ -0,0 +1,58 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<B, A> borsh::BorshSchema for Side<B, A>
+where
+    A: Display + Debug,
+    B: Display + Debug,
+    B: borsh::BorshSchema,
+    A: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < B as borsh::BorshSchema > ::declaration(), < A as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "Side", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct SideLeft<A>(
+            A,
+        )
+        where
+            A: Display + Debug;
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct SideRight<B>(
+            B,
+        )
+        where
+            B: Display + Debug;
+        <SideLeft<A> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <SideRight<B> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "Left".into(), < SideLeft < A > as
+                borsh::BorshSchema > ::declaration()), (u8::from(1u8) as i64, "Right"
+                .into(), < SideRight < B > as borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/enums/snapshots/with_funcs_attr.snap b/src/internals/schema/enums/snapshots/with_funcs_attr.snap
new file mode 100644
index 0000000..dfdfbc5
--- /dev/null
+++ b/src/internals/schema/enums/snapshots/with_funcs_attr.snap
@@ -0,0 +1,59 @@
+---
+source: src/internals/schema/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::BorshSchema for C<K, V>
+where
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "C", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct CC3(u64, u64);
+        #[allow(dead_code)]
+        #[derive(borsh::BorshSchema)]
+        #[borsh(crate = "borsh")]
+        struct CC4<K, V>(
+            u64,
+            #[borsh(
+                schema(
+                    with_funcs(
+                        declaration = "third_party_impl::declaration::<K, V>",
+                        definitions = "third_party_impl::add_definitions_recursively::<K, V>"
+                    )
+                )
+            )]
+            ThirdParty<K, V>,
+        );
+        <CC3 as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        <CC4<K, V> as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        let definition = borsh::schema::Definition::Enum {
+            tag_width: 1,
+            variants: borsh::__private::maybestd::vec![
+                (u8::from(0u8) as i64, "C3".into(), < CC3 as borsh::BorshSchema >
+                ::declaration()), (u8::from(1u8) as i64, "C4".into(), < CC4 < K, V > as
+                borsh::BorshSchema > ::declaration())
+            ],
+        };
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/check_with_funcs_skip_conflict.snap b/src/internals/schema/structs/snapshots/check_with_funcs_skip_conflict.snap
new file mode 100644
index 0000000..85f3b9e
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/check_with_funcs_skip_conflict.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`skip` cannot be used at the same time as `schema(with_funcs(...))`",
+)
diff --git a/src/internals/schema/structs/snapshots/generic_associated_type.snap b/src/internals/schema/structs/snapshots/generic_associated_type.snap
new file mode 100644
index 0000000..0ed467a
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_associated_type.snap
@@ -0,0 +1,50 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<V, T: Debug> borsh::BorshSchema for Parametrized<V, T>
+where
+    T: TraitName,
+    V: borsh::BorshSchema,
+    T::Associated: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < V as borsh::BorshSchema > ::declaration(), < T::Associated as
+            borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "Parametrized", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("field".to_string(), < T::Associated as borsh::BorshSchema >
+                ::declaration()), ("another".to_string(), < V as borsh::BorshSchema >
+                ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <T::Associated as borsh::BorshSchema>::add_definitions_recursively(
+                definitions,
+            );
+            <V as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_associated_type_param_override.snap b/src/internals/schema/structs/snapshots/generic_associated_type_param_override.snap
new file mode 100644
index 0000000..c172ef8
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_associated_type_param_override.snap
@@ -0,0 +1,50 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<V, T> borsh::BorshSchema for Parametrized<V, T>
+where
+    T: TraitName,
+    V: borsh::BorshSchema,
+    <T as TraitName>::Associated: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < V as borsh::BorshSchema > ::declaration(), < < T as TraitName >
+            ::Associated as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "Parametrized", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("field".to_string(), < < T as TraitName > ::Associated as
+                borsh::BorshSchema > ::declaration()), ("another".to_string(), < V as
+                borsh::BorshSchema > ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <<T as TraitName>::Associated as borsh::BorshSchema>::add_definitions_recursively(
+                definitions,
+            );
+            <V as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_associated_type_param_override2.snap b/src/internals/schema/structs/snapshots/generic_associated_type_param_override2.snap
new file mode 100644
index 0000000..5b57ba1
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_associated_type_param_override2.snap
@@ -0,0 +1,53 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<V, T> borsh::BorshSchema for Parametrized<V, T>
+where
+    T: TraitName,
+    V: borsh::BorshSchema,
+    T: borsh::BorshSchema,
+    <T as TraitName>::Associated: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < V as borsh::BorshSchema > ::declaration(), < T as borsh::BorshSchema >
+            ::declaration(), < < T as TraitName > ::Associated as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "Parametrized", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("field".to_string(), < (< T as TraitName > ::Associated, T) as
+                borsh::BorshSchema > ::declaration()), ("another".to_string(), < V as
+                borsh::BorshSchema > ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <(
+                <T as TraitName>::Associated,
+                T,
+            ) as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <V as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_associated_type_param_override_conflict.snap b/src/internals/schema/structs/snapshots/generic_associated_type_param_override_conflict.snap
new file mode 100644
index 0000000..1154582
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_associated_type_param_override_conflict.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: actual.unwrap_err()
+snapshot_kind: text
+---
+Error(
+    "`skip` cannot be used at the same time as `schema(params = ...)`",
+)
diff --git a/src/internals/schema/structs/snapshots/generic_named_fields_struct_borsh_skip.snap b/src/internals/schema/structs/snapshots/generic_named_fields_struct_borsh_skip.snap
new file mode 100644
index 0000000..85b1cf0
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_named_fields_struct_borsh_skip.snap
@@ -0,0 +1,42 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::BorshSchema for G<K, V, U>
+where
+    U: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < U as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "G", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("y".to_string(), < U as borsh::BorshSchema > ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <U as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip1.snap b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip1.snap
new file mode 100644
index 0000000..dc73049
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip1.snap
@@ -0,0 +1,40 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::BorshSchema for G<K, V, U>
+where
+    U: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < U as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "G", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![< U as borsh::BorshSchema > ::declaration()],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <U as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip2.snap b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip2.snap
new file mode 100644
index 0000000..421403b
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip2.snap
@@ -0,0 +1,47 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::BorshSchema for G<K, V, U>
+where
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "G", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![
+                < HashMap < K, V > as borsh::BorshSchema > ::declaration()
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <HashMap<
+                K,
+                V,
+            > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip3.snap b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip3.snap
new file mode 100644
index 0000000..b8b89dd
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip3.snap
@@ -0,0 +1,46 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<U, K, V> borsh::BorshSchema for G<U, K, V>
+where
+    U: borsh::BorshSchema,
+    K: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < U as borsh::BorshSchema > ::declaration(), < K as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "G", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![
+                < U as borsh::BorshSchema > ::declaration(), < K as borsh::BorshSchema >
+                ::declaration()
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <U as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <K as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip4.snap b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip4.snap
new file mode 100644
index 0000000..574c03d
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/generic_tuple_struct_borsh_skip4.snap
@@ -0,0 +1,38 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<C> borsh::BorshSchema for ASalad<C> {
+    fn declaration() -> borsh::schema::Declaration {
+        "ASalad".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![
+                < Tomatoes as borsh::BorshSchema > ::declaration(), < Oil as
+                borsh::BorshSchema > ::declaration()
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <Tomatoes as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <Oil as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/recursive_struct.snap b/src/internals/schema/structs/snapshots/recursive_struct.snap
new file mode 100644
index 0000000..4d85f8a
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/recursive_struct.snap
@@ -0,0 +1,42 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for CRecC {
+    fn declaration() -> borsh::schema::Declaration {
+        "CRecC".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("a".to_string(), < String as borsh::BorshSchema > ::declaration()), ("b"
+                .to_string(), < HashMap < String, CRecC > as borsh::BorshSchema >
+                ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <HashMap<
+                String,
+                CRecC,
+            > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/schema_param_override3.snap b/src/internals/schema/structs/snapshots/schema_param_override3.snap
new file mode 100644
index 0000000..1505aad
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/schema_param_override3.snap
@@ -0,0 +1,48 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: EntityRef, V> borsh::BorshSchema for A<K, V>
+where
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < V as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("x".to_string(), < PrimaryMap < K, V > as borsh::BorshSchema >
+                ::declaration()), ("y".to_string(), < String as borsh::BorshSchema >
+                ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <PrimaryMap<
+                K,
+                V,
+            > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/simple_generics.snap b/src/internals/schema/structs/snapshots/simple_generics.snap
new file mode 100644
index 0000000..b608421
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/simple_generics.snap
@@ -0,0 +1,50 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::BorshSchema for A<K, V>
+where
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("x".to_string(), < HashMap < K, V > as borsh::BorshSchema >
+                ::declaration()), ("y".to_string(), < String as borsh::BorshSchema >
+                ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <HashMap<
+                K,
+                V,
+            > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/simple_struct.snap b/src/internals/schema/structs/snapshots/simple_struct.snap
new file mode 100644
index 0000000..14707ae
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/simple_struct.snap
@@ -0,0 +1,38 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("x".to_string(), < u64 as borsh::BorshSchema > ::declaration()), ("y"
+                .to_string(), < String as borsh::BorshSchema > ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <u64 as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/simple_struct_with_custom_crate.snap b/src/internals/schema/structs/snapshots/simple_struct_with_custom_crate.snap
new file mode 100644
index 0000000..5f03a0b
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/simple_struct_with_custom_crate.snap
@@ -0,0 +1,43 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl reexporter::borsh::BorshSchema for A {
+    fn declaration() -> reexporter::borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut reexporter::borsh::__private::maybestd::collections::BTreeMap<
+            reexporter::borsh::schema::Declaration,
+            reexporter::borsh::schema::Definition,
+        >,
+    ) {
+        let fields = reexporter::borsh::schema::Fields::NamedFields(
+            reexporter::borsh::__private::maybestd::vec![
+                ("x".to_string(), < u64 as reexporter::borsh::BorshSchema >
+                ::declaration()), ("y".to_string(), < String as
+                reexporter::borsh::BorshSchema > ::declaration())
+            ],
+        );
+        let definition = reexporter::borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as reexporter::borsh::BorshSchema>::declaration())
+            .is_none();
+        reexporter::borsh::schema::add_definition(
+            <Self as reexporter::borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <u64 as reexporter::borsh::BorshSchema>::add_definitions_recursively(
+                definitions,
+            );
+            <String as reexporter::borsh::BorshSchema>::add_definitions_recursively(
+                definitions,
+            );
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/trailing_comma_generics.snap b/src/internals/schema/structs/snapshots/trailing_comma_generics.snap
new file mode 100644
index 0000000..eca7230
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/trailing_comma_generics.snap
@@ -0,0 +1,51 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::BorshSchema for A<K, V>
+where
+    K: Display + Debug,
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("x".to_string(), < HashMap < K, V > as borsh::BorshSchema >
+                ::declaration()), ("y".to_string(), < String as borsh::BorshSchema >
+                ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <HashMap<
+                K,
+                V,
+            > as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/tuple_struct.snap b/src/internals/schema/structs/snapshots/tuple_struct.snap
new file mode 100644
index 0000000..c80b3e1
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/tuple_struct.snap
@@ -0,0 +1,38 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![
+                < u64 as borsh::BorshSchema > ::declaration(), < String as
+                borsh::BorshSchema > ::declaration()
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <u64 as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/tuple_struct_params.snap b/src/internals/schema/structs/snapshots/tuple_struct_params.snap
new file mode 100644
index 0000000..1c8e91a
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/tuple_struct_params.snap
@@ -0,0 +1,46 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::BorshSchema for A<K, V>
+where
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![
+                < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+                ::declaration()
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <K as borsh::BorshSchema>::add_definitions_recursively(definitions);
+            <V as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/tuple_struct_partial_skip.snap b/src/internals/schema/structs/snapshots/tuple_struct_partial_skip.snap
new file mode 100644
index 0000000..5f31377
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/tuple_struct_partial_skip.snap
@@ -0,0 +1,36 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![
+                < String as borsh::BorshSchema > ::declaration()
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <String as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/tuple_struct_whole_skip.snap b/src/internals/schema/structs/snapshots/tuple_struct_whole_skip.snap
new file mode 100644
index 0000000..66f145a
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/tuple_struct_whole_skip.snap
@@ -0,0 +1,30 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::Empty;
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {}
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/unit_struct.snap b/src/internals/schema/structs/snapshots/unit_struct.snap
new file mode 100644
index 0000000..66f145a
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/unit_struct.snap
@@ -0,0 +1,30 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::BorshSchema for A {
+    fn declaration() -> borsh::schema::Declaration {
+        "A".to_string()
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::Empty;
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {}
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/with_funcs_attr.snap b/src/internals/schema/structs/snapshots/with_funcs_attr.snap
new file mode 100644
index 0000000..a605e37
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/with_funcs_attr.snap
@@ -0,0 +1,46 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::BorshSchema for A<K, V>
+where
+    K: borsh::BorshSchema,
+    V: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
+            ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::NamedFields(
+            borsh::__private::maybestd::vec![
+                ("x".to_string(), third_party_impl::declaration:: < K, V > ()), ("y"
+                .to_string(), < u64 as borsh::BorshSchema > ::declaration())
+            ],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            third_party_impl::add_definitions_recursively::<K, V>(definitions);
+            <u64 as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/schema/structs/snapshots/wrapper_struct.snap b/src/internals/schema/structs/snapshots/wrapper_struct.snap
new file mode 100644
index 0000000..623f6a2
--- /dev/null
+++ b/src/internals/schema/structs/snapshots/wrapper_struct.snap
@@ -0,0 +1,40 @@
+---
+source: src/internals/schema/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T> borsh::BorshSchema for A<T>
+where
+    T: borsh::BorshSchema,
+{
+    fn declaration() -> borsh::schema::Declaration {
+        let params = borsh::__private::maybestd::vec![
+            < T as borsh::BorshSchema > ::declaration()
+        ];
+        format!(r#"{}<{}>"#, "A", params.join(", "))
+    }
+    fn add_definitions_recursively(
+        definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
+            borsh::schema::Declaration,
+            borsh::schema::Definition,
+        >,
+    ) {
+        let fields = borsh::schema::Fields::UnnamedFields(
+            borsh::__private::maybestd::vec![< T as borsh::BorshSchema > ::declaration()],
+        );
+        let definition = borsh::schema::Definition::Struct {
+            fields,
+        };
+        let no_recursion_flag = definitions
+            .get(&<Self as borsh::BorshSchema>::declaration())
+            .is_none();
+        borsh::schema::add_definition(
+            <Self as borsh::BorshSchema>::declaration(),
+            definition,
+            definitions,
+        );
+        if no_recursion_flag {
+            <T as borsh::BorshSchema>::add_definitions_recursively(definitions);
+        }
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap b/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap
new file mode 100644
index 0000000..772fd60
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap
@@ -0,0 +1,22 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for X {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            X::A => 0u8,
+            X::B => 1u8,
+            X::C => 2u8,
+            X::D => 3u8,
+            X::E => 4u8,
+            X::F => 5u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap b/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap
new file mode 100644
index 0000000..68c1f8a
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap
@@ -0,0 +1,22 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for X {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            X::A => 0,
+            X::B => 20,
+            X::C => 20 + 1,
+            X::D => 20 + 1 + 1,
+            X::E => 10,
+            X::F => 10 + 1,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap b/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap
new file mode 100644
index 0000000..d9b640f
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap
@@ -0,0 +1,24 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for AAB {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            AAB::B { .. } => 0u8,
+            AAB::NegatedVariant { .. } => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            AAB::B { .. } => {}
+            AAB::NegatedVariant { beta, .. } => {
+                borsh::BorshSerialize::serialize(beta, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap b/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap
new file mode 100644
index 0000000..8595c1d
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap
@@ -0,0 +1,26 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for AB {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            AB::B { .. } => 0u8,
+            AB::NegatedVariant { .. } => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            AB::B { d, .. } => {
+                borsh::BorshSerialize::serialize(d, writer)?;
+            }
+            AB::NegatedVariant { beta, .. } => {
+                borsh::BorshSerialize::serialize(beta, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap b/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap
new file mode 100644
index 0000000..1a0a706
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap
@@ -0,0 +1,24 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for AATTB {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            AATTB::B(..) => 0u8,
+            AATTB::NegatedVariant { .. } => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            AATTB::B(_id0, _id1) => {}
+            AATTB::NegatedVariant { beta, .. } => {
+                borsh::BorshSerialize::serialize(beta, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/bound_generics.snap b/src/internals/serialize/enums/snapshots/bound_generics.snap
new file mode 100644
index 0000000..c2363e0
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/bound_generics.snap
@@ -0,0 +1,34 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V, U> borsh::ser::BorshSerialize for A<K, V, U>
+where
+    V: Value,
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            A::B { .. } => 0u8,
+            A::C(..) => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            A::B { x, y, .. } => {
+                borsh::BorshSerialize::serialize(x, writer)?;
+                borsh::BorshSerialize::serialize(y, writer)?;
+            }
+            A::C(id0, id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+                borsh::BorshSerialize::serialize(id1, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap b/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap
new file mode 100644
index 0000000..da7df57
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap
@@ -0,0 +1,32 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Ord, V> borsh::ser::BorshSerialize for C<K, V>
+where
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            C::C3(..) => 0u8,
+            C::C4 { .. } => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            C::C3(id0, id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+                borsh::BorshSerialize::serialize(id1, writer)?;
+            }
+            C::C4 { x, y, .. } => {
+                borsh::BorshSerialize::serialize(x, writer)?;
+                third_party_impl::serialize_third_party(y, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap b/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap
new file mode 100644
index 0000000..6c692f1
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap
@@ -0,0 +1,32 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V, U> borsh::ser::BorshSerialize for A<K, V, U>
+where
+    V: Value,
+    K: borsh::ser::BorshSerialize,
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            A::B { .. } => 0u8,
+            A::C(..) => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            A::B { y, .. } => {
+                borsh::BorshSerialize::serialize(y, writer)?;
+            }
+            A::C(id0, id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+                borsh::BorshSerialize::serialize(id1, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap b/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap
new file mode 100644
index 0000000..092b5df
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap
@@ -0,0 +1,32 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V, U> borsh::ser::BorshSerialize for A<K, V, U>
+where
+    V: Value,
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            A::B { .. } => 0u8,
+            A::C(..) => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            A::B { x, y, .. } => {
+                borsh::BorshSerialize::serialize(x, writer)?;
+                borsh::BorshSerialize::serialize(y, writer)?;
+            }
+            A::C(id0, _id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap b/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap
new file mode 100644
index 0000000..be302fa
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap
@@ -0,0 +1,32 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T: Debug, U> borsh::ser::BorshSerialize for A<T, U>
+where
+    T: borsh::ser::BorshSerialize + PartialOrd,
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            A::C { .. } => 0u8,
+            A::D(..) => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            A::C { a, b, .. } => {
+                borsh::BorshSerialize::serialize(a, writer)?;
+                borsh::BorshSerialize::serialize(b, writer)?;
+            }
+            A::D(id0, id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+                borsh::BorshSerialize::serialize(id1, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap b/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap
new file mode 100644
index 0000000..2b53430
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap
@@ -0,0 +1,30 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for X {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            X::A(..) => 0u8,
+            X::B => 1u8,
+            X::C { .. } => 2u8,
+            X::D => 3u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            X::A(id0) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+            }
+            X::C { x, y, .. } => {
+                borsh::BorshSerialize::serialize(x, writer)?;
+                borsh::BorshSerialize::serialize(y, writer)?;
+            }
+            _ => {}
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/recursive_enum.snap b/src/internals/serialize/enums/snapshots/recursive_enum.snap
new file mode 100644
index 0000000..0200802
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/recursive_enum.snap
@@ -0,0 +1,33 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V> borsh::ser::BorshSerialize for A<K, V>
+where
+    V: Value,
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            A::B { .. } => 0u8,
+            A::C(..) => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            A::B { x, y, .. } => {
+                borsh::BorshSerialize::serialize(x, writer)?;
+                borsh::BorshSerialize::serialize(y, writer)?;
+            }
+            A::C(id0, id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+                borsh::BorshSerialize::serialize(id1, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap b/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap
new file mode 100644
index 0000000..3d95a6d
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap
@@ -0,0 +1,27 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl reexporter::borsh::ser::BorshSerialize for AB {
+    fn serialize<__W: reexporter::borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), reexporter::borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            AB::B { .. } => 0u8,
+            AB::NegatedVariant { .. } => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            AB::B { c, d, .. } => {
+                reexporter::borsh::BorshSerialize::serialize(c, writer)?;
+                reexporter::borsh::BorshSerialize::serialize(d, writer)?;
+            }
+            AB::NegatedVariant { beta, .. } => {
+                reexporter::borsh::BorshSerialize::serialize(beta, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/simple_generics.snap b/src/internals/serialize/enums/snapshots/simple_generics.snap
new file mode 100644
index 0000000..0a704a2
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/simple_generics.snap
@@ -0,0 +1,33 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::ser::BorshSerialize for A<K, V, U>
+where
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            A::B { .. } => 0u8,
+            A::C(..) => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            A::B { x, y, .. } => {
+                borsh::BorshSerialize::serialize(x, writer)?;
+                borsh::BorshSerialize::serialize(y, writer)?;
+            }
+            A::C(id0, id1) => {
+                borsh::BorshSerialize::serialize(id0, writer)?;
+                borsh::BorshSerialize::serialize(id1, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/enums/snapshots/struct_variant_field.snap b/src/internals/serialize/enums/snapshots/struct_variant_field.snap
new file mode 100644
index 0000000..f7e13bb
--- /dev/null
+++ b/src/internals/serialize/enums/snapshots/struct_variant_field.snap
@@ -0,0 +1,27 @@
+---
+source: src/internals/serialize/enums/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for AB {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        let variant_idx: u8 = match self {
+            AB::B { .. } => 0u8,
+            AB::NegatedVariant { .. } => 1u8,
+        };
+        writer.write_all(&variant_idx.to_le_bytes())?;
+        match self {
+            AB::B { c, d, .. } => {
+                borsh::BorshSerialize::serialize(c, writer)?;
+                borsh::BorshSerialize::serialize(d, writer)?;
+            }
+            AB::NegatedVariant { beta, .. } => {
+                borsh::BorshSerialize::serialize(beta, writer)?;
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/bound_generics.snap b/src/internals/serialize/structs/snapshots/bound_generics.snap
new file mode 100644
index 0000000..8854ab9
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/bound_generics.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Key, V> borsh::ser::BorshSerialize for A<K, V>
+where
+    V: Value,
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.x, writer)?;
+        borsh::BorshSerialize::serialize(&self.y, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap b/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap
new file mode 100644
index 0000000..2609afb
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap
@@ -0,0 +1,19 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K: Ord, V> borsh::ser::BorshSerialize for A<K, V>
+where
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        third_party_impl::serialize_third_party(&self.x, writer)?;
+        borsh::BorshSerialize::serialize(&self.y, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap b/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap
new file mode 100644
index 0000000..f6e9c2a
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap
@@ -0,0 +1,8 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: err
+snapshot_kind: text
+---
+Error(
+    "`skip` cannot be used at the same time as `serialize_with` or `deserialize_with`",
+)
diff --git a/src/internals/serialize/structs/snapshots/generic_associated_type.snap b/src/internals/serialize/structs/snapshots/generic_associated_type.snap
new file mode 100644
index 0000000..6737517
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/generic_associated_type.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T, V> borsh::ser::BorshSerialize for Parametrized<T, V>
+where
+    T: TraitName,
+    T::Associated: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.field, writer)?;
+        borsh::BorshSerialize::serialize(&self.another, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap b/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap
new file mode 100644
index 0000000..527f39e
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap
@@ -0,0 +1,17 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::ser::BorshSerialize for G<K, V, U>
+where
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.y, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap b/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap
new file mode 100644
index 0000000..0f504e1
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap
@@ -0,0 +1,19 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T: Debug, U> borsh::ser::BorshSerialize for C<T, U>
+where
+    T: borsh::ser::BorshSerialize + PartialOrd,
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.a, writer)?;
+        borsh::BorshSerialize::serialize(&self.b, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap b/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap
new file mode 100644
index 0000000..993acf3
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap
@@ -0,0 +1,17 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::ser::BorshSerialize for G<K, V, U>
+where
+    U: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.1, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap b/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap
new file mode 100644
index 0000000..705bca3
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap
@@ -0,0 +1,18 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V, U> borsh::ser::BorshSerialize for G<K, V, U>
+where
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.0, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap b/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap
new file mode 100644
index 0000000..f76c6d2
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap
@@ -0,0 +1,20 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T, V> borsh::ser::BorshSerialize for Parametrized<T, V>
+where
+    T: TraitName,
+    V: borsh::ser::BorshSerialize,
+    <T as TraitName>::Associated: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.field, writer)?;
+        borsh::BorshSerialize::serialize(&self.another, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/recursive_struct.snap b/src/internals/serialize/structs/snapshots/recursive_struct.snap
new file mode 100644
index 0000000..440c28c
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/recursive_struct.snap
@@ -0,0 +1,15 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for CRecC {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.a, writer)?;
+        borsh::BorshSerialize::serialize(&self.b, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap b/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap
new file mode 100644
index 0000000..7ddac32
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap
@@ -0,0 +1,18 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<T> borsh::ser::BorshSerialize for TupleA<T>
+where
+    T: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.0, writer)?;
+        borsh::BorshSerialize::serialize(&self.1, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/simple_generics.snap b/src/internals/serialize/structs/snapshots/simple_generics.snap
new file mode 100644
index 0000000..ad4fe59
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/simple_generics.snap
@@ -0,0 +1,19 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl<K, V> borsh::ser::BorshSerialize for A<K, V>
+where
+    K: borsh::ser::BorshSerialize,
+    V: borsh::ser::BorshSerialize,
+{
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.x, writer)?;
+        borsh::BorshSerialize::serialize(&self.y, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/simple_struct.snap b/src/internals/serialize/structs/snapshots/simple_struct.snap
new file mode 100644
index 0000000..69b3283
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/simple_struct.snap
@@ -0,0 +1,15 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl borsh::ser::BorshSerialize for A {
+    fn serialize<__W: borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), borsh::io::Error> {
+        borsh::BorshSerialize::serialize(&self.x, writer)?;
+        borsh::BorshSerialize::serialize(&self.y, writer)?;
+        Ok(())
+    }
+}
diff --git a/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap b/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap
new file mode 100644
index 0000000..3916f03
--- /dev/null
+++ b/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap
@@ -0,0 +1,15 @@
+---
+source: src/internals/serialize/structs/mod.rs
+expression: pretty_print_syn_str(&actual).unwrap()
+snapshot_kind: text
+---
+impl reexporter::borsh::ser::BorshSerialize for A {
+    fn serialize<__W: reexporter::borsh::io::Write>(
+        &self,
+        writer: &mut __W,
+    ) -> ::core::result::Result<(), reexporter::borsh::io::Error> {
+        reexporter::borsh::BorshSerialize::serialize(&self.x, writer)?;
+        reexporter::borsh::BorshSerialize::serialize(&self.y, writer)?;
+        Ok(())
+    }
+}
