This is an automated email from the ASF dual-hosted git repository.

Kriskras99 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 77531c6  refactor: Improve code structure of the derive code (#560)
77531c6 is described below

commit 77531c692565729142cac0741d3a384bc59d600c
Author: Kriskras99 <[email protected]>
AuthorDate: Tue Jun 23 21:07:10 2026 +0200

    refactor: Improve code structure of the derive code (#560)
    
    * refactor: Improve code structure of the derive code
    
    This also changes the implementation of `utils::field_aliases` to remove
    the unnecessary `try_from`.
    
    * fix: Review feedback
---
 avro_derive/src/attributes/serde.rs                |   2 +-
 avro_derive/src/fields.rs                          | 182 ++++++++++
 avro_derive/src/lib.rs                             | 368 +--------------------
 avro_derive/src/structs.rs                         | 185 +++++++++++
 avro_derive/src/utils.rs                           |  67 ++++
 .../avro_3709_record_field_attributes.expanded.rs  |  14 +-
 .../avro_rs_207_rename_all_attribute.expanded.rs   |   8 +-
 ...name_attr_over_rename_all_attribute.expanded.rs |   8 +-
 .../tests/expanded/avro_rs_501_basic.expanded.rs   |   8 +-
 .../expanded/avro_rs_501_namespace.expanded.rs     |   8 +-
 .../expanded/avro_rs_501_reference.expanded.rs     |   8 +-
 .../avro_rs_501_struct_with_optional.expanded.rs   |   4 +-
 .../tests/ui/avro_rs_397_with_expr_string.stderr   |   2 +-
 13 files changed, 474 insertions(+), 390 deletions(-)

diff --git a/avro_derive/src/attributes/serde.rs 
b/avro_derive/src/attributes/serde.rs
index 6149752..69d594b 100644
--- a/avro_derive/src/attributes/serde.rs
+++ b/avro_derive/src/attributes/serde.rs
@@ -254,8 +254,8 @@ pub struct FieldAttributes {
 #[cfg(test)]
 mod tests {
     use crate::{
-        RenameRule,
         attributes::serde::{ContainerAttributes, RenameAll, SerdeDefault},
+        case::RenameRule,
     };
     use darling::FromAttributes;
     use syn::DeriveInput;
diff --git a/avro_derive/src/fields.rs b/avro_derive/src/fields.rs
new file mode 100644
index 0000000..f6bcb80
--- /dev/null
+++ b/avro_derive/src/fields.rs
@@ -0,0 +1,182 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::attributes::{FieldDefault, With};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::spanned::Spanned;
+use syn::{Expr, Field, Type};
+
+pub fn field_to_schema_expr(field: &Field, with: With) -> Result<TokenStream, 
Vec<syn::Error>> {
+    match with {
+        With::Trait => Ok(type_to_schema_expr(&field.ty)?),
+        With::Serde(path) => {
+            Ok(quote! { #path::get_schema_in_ctxt(named_schemas, 
enclosing_namespace) })
+        }
+        With::Expr(Expr::Closure(closure)) => {
+            if closure.inputs.is_empty() {
+                Ok(quote! { (#closure)() })
+            } else {
+                Err(vec![syn::Error::new(
+                    field.span(),
+                    "Expected closure with 0 parameters",
+                )])
+            }
+        }
+        With::Expr(Expr::Path(path)) => Ok(quote! { #path(named_schemas, 
enclosing_namespace) }),
+        With::Expr(_expr) => Err(vec![syn::Error::new(
+            field.span(),
+            "Invalid expression, expected a function or a closure",
+        )]),
+    }
+}
+
+pub fn field_to_record_fields_expr(
+    field: &Field,
+    with: With,
+) -> Result<TokenStream, Vec<syn::Error>> {
+    match with {
+        With::Trait => Ok(type_to_record_fields_expr(&field.ty)?),
+        With::Serde(path) => {
+            Ok(quote! { #path::get_record_fields_in_ctxt(named_schemas, 
enclosing_namespace) })
+        }
+        With::Expr(Expr::Closure(closure)) => {
+            if closure.inputs.is_empty() {
+                Ok(quote! {
+                    ::apache_avro::serde::get_record_fields_in_ctxt(
+                        named_schemas,
+                        enclosing_namespace,
+                        |_, _| (#closure)(),
+                    )
+                })
+            } else {
+                Err(vec![syn::Error::new(
+                    field.span(),
+                    "Expected closure with 0 parameters",
+                )])
+            }
+        }
+        With::Expr(Expr::Path(path)) => Ok(quote! {
+            ::apache_avro::serde::get_record_fields_in_ctxt(named_schemas, 
enclosing_namespace, #path)
+        }),
+        With::Expr(_expr) => Err(vec![syn::Error::new(
+            field.span(),
+            "Invalid expression, expected a function or a closure",
+        )]),
+    }
+}
+
+pub fn field_to_field_default_expr(
+    field: &Field,
+    default: FieldDefault,
+) -> Result<TokenStream, Vec<syn::Error>> {
+    match default {
+        FieldDefault::Disabled => Ok(quote! { ::std::option::Option::None }),
+        FieldDefault::Trait => type_to_field_default_expr(&field.ty),
+        FieldDefault::Value(default_value) => {
+            let _: serde_json::Value = 
serde_json::from_str(&default_value[..]).map_err(|e| {
+                vec![syn::Error::new(
+                    field.span(),
+                    format!("Invalid avro default json: \n{e}"),
+                )]
+            })?;
+            Ok(quote! {
+                
::std::option::Option::Some(::serde_json::from_str(#default_value).expect("Unreachable!
 This parsed successfully at compile time!"))
+            })
+        }
+    }
+}
+
+/// Takes in the Tokens of a type and returns the tokens of an expression with 
return type `Schema`
+fn type_to_schema_expr(ty: &Type) -> Result<TokenStream, Vec<syn::Error>> {
+    match ty {
+        Type::Array(_) | Type::Slice(_) | Type::Path(_) | Type::Reference(_) 
=> Ok(
+            quote! {<#ty as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)},
+        ),
+        Type::Ptr(_) => Err(vec![syn::Error::new_spanned(
+            ty,
+            "AvroSchema: derive does not support raw pointers",
+        )]),
+        Type::Tuple(_) => Err(vec![syn::Error::new_spanned(
+            ty,
+            "AvroSchema: derive does not support tuples",
+        )]),
+        _ => Err(vec![syn::Error::new_spanned(
+            ty,
+            format!(
+                "AvroSchema: Unexpected type encountered! Please open an issue 
if this kind of type should be supported: {ty:?}"
+            ),
+        )]),
+    }
+}
+
+fn type_to_record_fields_expr(ty: &Type) -> Result<TokenStream, 
Vec<syn::Error>> {
+    match ty {
+        Type::Array(_) | Type::Slice(_) | Type::Path(_) | Type::Reference(_) 
=> Ok(
+            quote! {<#ty as :: 
apache_avro::AvroSchemaComponent>::get_record_fields_in_ctxt(named_schemas, 
enclosing_namespace)},
+        ),
+        Type::Ptr(_) => Err(vec![syn::Error::new_spanned(
+            ty,
+            "AvroSchema: derive does not support raw pointers",
+        )]),
+        Type::Tuple(_) => Err(vec![syn::Error::new_spanned(
+            ty,
+            "AvroSchema: derive does not support tuples",
+        )]),
+        _ => Err(vec![syn::Error::new_spanned(
+            ty,
+            format!(
+                "AvroSchema: Unexpected type encountered! Please open an issue 
if this kind of type should be supported: {ty:?}"
+            ),
+        )]),
+    }
+}
+
+fn type_to_field_default_expr(ty: &Type) -> Result<TokenStream, 
Vec<syn::Error>> {
+    match ty {
+        Type::Array(_) | Type::Slice(_) | Type::Path(_) | Type::Reference(_) 
=> {
+            Ok(quote! {<#ty as :: 
apache_avro::AvroSchemaComponent>::field_default()})
+        }
+        Type::Ptr(_) => Err(vec![syn::Error::new_spanned(
+            ty,
+            "AvroSchema: derive does not support raw pointers",
+        )]),
+        Type::Tuple(_) => Err(vec![syn::Error::new_spanned(
+            ty,
+            "AvroSchema: derive does not support tuples",
+        )]),
+        _ => Err(vec![syn::Error::new_spanned(
+            ty,
+            format!(
+                "AvroSchema: Unexpected type encountered! Please open an issue 
if this kind of type should be supported: {ty:?}"
+            ),
+        )]),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use pretty_assertions::assert_eq;
+
+    #[test]
+    fn test_trait_cast() {
+        
assert_eq!(type_to_schema_expr(&syn::parse2::<Type>(quote!{i32}).unwrap()).unwrap().to_string(),
 quote!{<i32 as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)}.to_string());
+        
assert_eq!(type_to_schema_expr(&syn::parse2::<Type>(quote!{Vec<T>}).unwrap()).unwrap().to_string(),
 quote!{<Vec<T> as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)}.to_string());
+        
assert_eq!(type_to_schema_expr(&syn::parse2::<Type>(quote!{AnyType}).unwrap()).unwrap().to_string(),
 quote!{<AnyType as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)}.to_string());
+    }
+}
diff --git a/avro_derive/src/lib.rs b/avro_derive/src/lib.rs
index d63ed8f..e2bc329 100644
--- a/avro_derive/src/lib.rs
+++ b/avro_derive/src/lib.rs
@@ -32,19 +32,18 @@
 mod attributes;
 mod case;
 mod enums;
+mod fields;
+mod structs;
+mod utils;
 
-use proc_macro2::{Span, TokenStream};
+use proc_macro2::TokenStream;
 use quote::quote;
-use syn::{
-    DataStruct, DeriveInput, Expr, Field, Fields, Generics, Ident, Type, 
parse_macro_input,
-    spanned::Spanned,
-};
+use syn::{DeriveInput, Generics, Ident, parse_macro_input, spanned::Spanned};
 
+use crate::attributes::NamedTypeOptions;
 use crate::enums::get_data_enum_schema_def;
-use crate::{
-    attributes::{FieldDefault, FieldOptions, NamedTypeOptions, With},
-    case::RenameRule,
-};
+use crate::structs::{get_struct_schema_def, get_transparent_struct_schema_def};
+use crate::utils::{aliases, preserve_optional, to_compile_errors};
 
 #[proc_macro_derive(AvroSchema, attributes(avro, serde))]
 // Templated from Serde
@@ -146,354 +145,3 @@ fn handle_named_schemas(full_schema_name: &str, 
schema_def: &TokenStream) -> Tok
         }
     }
 }
-
-/// Generate a schema definition for a struct.
-fn get_struct_schema_def(
-    container_attrs: &NamedTypeOptions,
-    data_struct: DataStruct,
-    ident_span: Span,
-) -> Result<(TokenStream, TokenStream), Vec<syn::Error>> {
-    let mut record_field_exprs = vec![];
-    match data_struct.fields {
-        Fields::Named(a) => {
-            for field in a.named {
-                let mut name = field
-                    .ident
-                    .as_ref()
-                    .expect("Field must have a name")
-                    .to_string();
-                if let Some(raw_name) = name.strip_prefix("r#") {
-                    name = raw_name.to_string();
-                }
-                let field_attrs = FieldOptions::new(&field.attrs, 
field.span())?;
-                let doc = preserve_optional(field_attrs.doc);
-                match (field_attrs.rename, container_attrs.rename_all) {
-                    (Some(rename), _) => {
-                        name = rename;
-                    }
-                    (None, rename_all) if rename_all != RenameRule::None => {
-                        name = rename_all.apply_to_field(&name);
-                    }
-                    _ => {}
-                }
-                if field_attrs.skip {
-                    continue;
-                } else if field_attrs.flatten {
-                    // Inline the fields of the child record at runtime, as we 
don't have access to
-                    // the schema here.
-                    let get_record_fields =
-                        get_field_get_record_fields_expr(&field, 
field_attrs.with)?;
-                    record_field_exprs.push(quote! {
-                        if let Some(flattened_fields) = #get_record_fields {
-                            schema_fields.extend(flattened_fields);
-                        } else {
-                            panic!("{} does not have any fields to flatten 
to", stringify!(#field));
-                        }
-                    });
-
-                    // Don't add this field as it's been replaced by the child 
record fields
-                    continue;
-                }
-                let default_value = match field_attrs.default {
-                    FieldDefault::Disabled => quote! { 
::std::option::Option::None },
-                    FieldDefault::Trait => 
type_to_field_default_expr(&field.ty)?,
-                    FieldDefault::Value(default_value) => {
-                        let _: serde_json::Value = 
serde_json::from_str(&default_value[..])
-                            .map_err(|e| {
-                                vec![syn::Error::new(
-                                    field.ident.span(),
-                                    format!("Invalid avro default json: 
\n{e}"),
-                                )]
-                            })?;
-                        quote! {
-                            
::std::option::Option::Some(::serde_json::from_str(#default_value).expect("Unreachable!
 This parsed at compile time!"))
-                        }
-                    }
-                };
-                let aliases = field_aliases(&field_attrs.alias);
-                let schema_expr = get_field_schema_expr(&field, 
field_attrs.with)?;
-                record_field_exprs.push(quote! {
-                    schema_fields.push(::apache_avro::schema::RecordField {
-                        name: #name.to_string(),
-                        doc: #doc,
-                        default: #default_value,
-                        aliases: #aliases,
-                        schema: #schema_expr,
-                        custom_attributes: ::std::collections::BTreeMap::new(),
-                    });
-                });
-            }
-        }
-        Fields::Unnamed(_) => {
-            return Err(vec![syn::Error::new(
-                ident_span,
-                "AvroSchema derive does not work for tuple structs",
-            )]);
-        }
-        Fields::Unit => {
-            return Err(vec![syn::Error::new(
-                ident_span,
-                "AvroSchema derive does not work for unit structs",
-            )]);
-        }
-    }
-
-    let record_doc = preserve_optional(container_attrs.doc.as_ref());
-    let record_aliases = aliases(&container_attrs.aliases);
-    let full_schema_name = &container_attrs.name;
-
-    // When flatten is involved, there will be more but we don't know how 
many. This optimises for
-    // the most common case where there is no flatten.
-    let minimum_fields = record_field_exprs.len();
-
-    let schema_def = quote! {
-        {
-            let mut schema_fields = 
::std::vec::Vec::with_capacity(#minimum_fields);
-            #(#record_field_exprs)*
-            let schema_field_set: ::std::collections::HashSet<_> = 
schema_fields.iter().map(|rf| &rf.name).collect();
-            assert_eq!(schema_fields.len(), schema_field_set.len(), "Duplicate 
field names found: {schema_fields:?}");
-            let name = 
::apache_avro::schema::Name::new(#full_schema_name).expect(&format!("Unable to 
parse struct name for schema {}", #full_schema_name)[..]);
-            let lookup: ::std::collections::BTreeMap<String, usize> = 
schema_fields
-                .iter()
-                .enumerate()
-                .map(|(position, field)| (field.name.to_owned(), position))
-                .collect();
-            
::apache_avro::schema::Schema::Record(::apache_avro::schema::RecordSchema {
-                name,
-                aliases: #record_aliases,
-                doc: #record_doc,
-                fields: schema_fields,
-                lookup,
-                attributes: ::std::collections::BTreeMap::new(),
-            })
-        }
-    };
-    let record_fields = quote! {
-        let mut schema_fields = 
::std::vec::Vec::with_capacity(#minimum_fields);
-        #(#record_field_exprs)*
-        ::std::option::Option::Some(schema_fields)
-    };
-
-    Ok((schema_def, record_fields))
-}
-
-/// Use the schema definition of the only field in the struct as the schema
-fn get_transparent_struct_schema_def(
-    fields: Fields,
-    input_span: Span,
-) -> Result<(TokenStream, TokenStream), Vec<syn::Error>> {
-    match fields {
-        Fields::Named(fields_named) => {
-            let mut found = None;
-            for field in fields_named.named {
-                let attrs = FieldOptions::new(&field.attrs, field.span())?;
-                if attrs.skip {
-                    continue;
-                }
-                if found.replace((field, attrs)).is_some() {
-                    return Err(vec![syn::Error::new(
-                        input_span,
-                        "AvroSchema: #[serde(transparent)] is only allowed on 
structs with one unskipped field",
-                    )]);
-                }
-            }
-
-            if let Some((field, attrs)) = found {
-                Ok((
-                    get_field_schema_expr(&field, attrs.with.clone())?,
-                    get_field_get_record_fields_expr(&field, attrs.with)?,
-                ))
-            } else {
-                Err(vec![syn::Error::new(
-                    input_span,
-                    "AvroSchema: #[serde(transparent)] is only allowed on 
structs with one unskipped field",
-                )])
-            }
-        }
-        Fields::Unnamed(_) => Err(vec![syn::Error::new(
-            input_span,
-            "AvroSchema: derive does not work for tuple structs",
-        )]),
-        Fields::Unit => Err(vec![syn::Error::new(
-            input_span,
-            "AvroSchema: derive does not work for unit structs",
-        )]),
-    }
-}
-
-fn get_field_schema_expr(field: &Field, with: With) -> Result<TokenStream, 
Vec<syn::Error>> {
-    match with {
-        With::Trait => Ok(type_to_schema_expr(&field.ty)?),
-        With::Serde(path) => {
-            Ok(quote! { #path::get_schema_in_ctxt(named_schemas, 
enclosing_namespace) })
-        }
-        With::Expr(Expr::Closure(closure)) => {
-            if closure.inputs.is_empty() {
-                Ok(quote! { (#closure)() })
-            } else {
-                Err(vec![syn::Error::new(
-                    field.span(),
-                    "Expected closure with 0 parameters",
-                )])
-            }
-        }
-        With::Expr(Expr::Path(path)) => Ok(quote! { #path(named_schemas, 
enclosing_namespace) }),
-        With::Expr(_expr) => Err(vec![syn::Error::new(
-            field.span(),
-            "Invalid expression, expected function or closure",
-        )]),
-    }
-}
-
-fn get_field_get_record_fields_expr(
-    field: &Field,
-    with: With,
-) -> Result<TokenStream, Vec<syn::Error>> {
-    match with {
-        With::Trait => Ok(type_to_get_record_fields_expr(&field.ty)?),
-        With::Serde(path) => {
-            Ok(quote! { #path::get_record_fields_in_ctxt(named_schemas, 
enclosing_namespace) })
-        }
-        With::Expr(Expr::Closure(closure)) => {
-            if closure.inputs.is_empty() {
-                Ok(quote! {
-                    ::apache_avro::serde::get_record_fields_in_ctxt(
-                        named_schemas,
-                        enclosing_namespace,
-                        |_, _| (#closure)(),
-                    )
-                })
-            } else {
-                Err(vec![syn::Error::new(
-                    field.span(),
-                    "Expected closure with 0 parameters",
-                )])
-            }
-        }
-        With::Expr(Expr::Path(path)) => Ok(quote! {
-            ::apache_avro::serde::get_record_fields_in_ctxt(named_schemas, 
enclosing_namespace, #path)
-        }),
-        With::Expr(_expr) => Err(vec![syn::Error::new(
-            field.span(),
-            "Invalid expression, expected function or closure",
-        )]),
-    }
-}
-
-/// Takes in the Tokens of a type and returns the tokens of an expression with 
return type `Schema`
-fn type_to_schema_expr(ty: &Type) -> Result<TokenStream, Vec<syn::Error>> {
-    match ty {
-        Type::Array(_) | Type::Slice(_) | Type::Path(_) | Type::Reference(_) 
=> Ok(
-            quote! {<#ty as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)},
-        ),
-        Type::Ptr(_) => Err(vec![syn::Error::new_spanned(
-            ty,
-            "AvroSchema: derive does not support raw pointers",
-        )]),
-        Type::Tuple(_) => Err(vec![syn::Error::new_spanned(
-            ty,
-            "AvroSchema: derive does not support tuples",
-        )]),
-        _ => Err(vec![syn::Error::new_spanned(
-            ty,
-            format!(
-                "AvroSchema: Unexpected type encountered! Please open an issue 
if this kind of type should be supported: {ty:?}"
-            ),
-        )]),
-    }
-}
-
-fn type_to_get_record_fields_expr(ty: &Type) -> Result<TokenStream, 
Vec<syn::Error>> {
-    match ty {
-        Type::Array(_) | Type::Slice(_) | Type::Path(_) | Type::Reference(_) 
=> Ok(
-            quote! {<#ty as :: 
apache_avro::AvroSchemaComponent>::get_record_fields_in_ctxt(named_schemas, 
enclosing_namespace)},
-        ),
-        Type::Ptr(_) => Err(vec![syn::Error::new_spanned(
-            ty,
-            "AvroSchema: derive does not support raw pointers",
-        )]),
-        Type::Tuple(_) => Err(vec![syn::Error::new_spanned(
-            ty,
-            "AvroSchema: derive does not support tuples",
-        )]),
-        _ => Err(vec![syn::Error::new_spanned(
-            ty,
-            format!(
-                "AvroSchema: Unexpected type encountered! Please open an issue 
if this kind of type should be supported: {ty:?}"
-            ),
-        )]),
-    }
-}
-
-fn type_to_field_default_expr(ty: &Type) -> Result<TokenStream, 
Vec<syn::Error>> {
-    match ty {
-        Type::Array(_) | Type::Slice(_) | Type::Path(_) | Type::Reference(_) 
=> {
-            Ok(quote! {<#ty as :: 
apache_avro::AvroSchemaComponent>::field_default()})
-        }
-        Type::Ptr(_) => Err(vec![syn::Error::new_spanned(
-            ty,
-            "AvroSchema: derive does not support raw pointers",
-        )]),
-        Type::Tuple(_) => Err(vec![syn::Error::new_spanned(
-            ty,
-            "AvroSchema: derive does not support tuples",
-        )]),
-        _ => Err(vec![syn::Error::new_spanned(
-            ty,
-            format!(
-                "AvroSchema: Unexpected type encountered! Please open an issue 
if this kind of type should be supported: {ty:?}"
-            ),
-        )]),
-    }
-}
-
-/// Stolen from serde
-fn to_compile_errors(errors: impl AsRef<[syn::Error]>) -> 
proc_macro2::TokenStream {
-    let compile_errors = 
errors.as_ref().iter().map(syn::Error::to_compile_error);
-    quote!(#(#compile_errors)*)
-}
-
-fn preserve_optional(op: Option<impl quote::ToTokens>) -> TokenStream {
-    if let Some(tt) = op {
-        quote! {::std::option::Option::Some(#tt.into())}
-    } else {
-        quote! {::std::option::Option::None}
-    }
-}
-
-fn aliases(op: &[impl quote::ToTokens]) -> TokenStream {
-    let items: Vec<TokenStream> = op
-        .iter()
-        .map(|tt| quote! {#tt.try_into().expect("Alias is invalid")})
-        .collect();
-    if items.is_empty() {
-        quote! {::std::option::Option::None}
-    } else {
-        quote! {::std::option::Option::Some(vec![#(#items),*])}
-    }
-}
-
-fn field_aliases(op: &[impl quote::ToTokens]) -> TokenStream {
-    let items: Vec<TokenStream> = op
-        .iter()
-        .map(|tt| quote! {#tt.try_into().expect("Alias is invalid")})
-        .collect();
-    if items.is_empty() {
-        quote! {::std::vec::Vec::new()}
-    } else {
-        quote! {vec![#(#items),*]}
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use pretty_assertions::assert_eq;
-
-    #[test]
-    fn test_trait_cast() {
-        
assert_eq!(type_to_schema_expr(&syn::parse2::<Type>(quote!{i32}).unwrap()).unwrap().to_string(),
 quote!{<i32 as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)}.to_string());
-        
assert_eq!(type_to_schema_expr(&syn::parse2::<Type>(quote!{Vec<T>}).unwrap()).unwrap().to_string(),
 quote!{<Vec<T> as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)}.to_string());
-        
assert_eq!(type_to_schema_expr(&syn::parse2::<Type>(quote!{AnyType}).unwrap()).unwrap().to_string(),
 quote!{<AnyType as :: 
apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(named_schemas, 
enclosing_namespace)}.to_string());
-    }
-}
diff --git a/avro_derive/src/structs.rs b/avro_derive/src/structs.rs
new file mode 100644
index 0000000..db51bd1
--- /dev/null
+++ b/avro_derive/src/structs.rs
@@ -0,0 +1,185 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::attributes::{FieldOptions, NamedTypeOptions};
+use crate::case::RenameRule;
+use crate::fields::{
+    field_to_field_default_expr, field_to_record_fields_expr, 
field_to_schema_expr,
+};
+use crate::utils::{aliases, field_aliases, preserve_optional};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::spanned::Spanned;
+use syn::{DataStruct, Fields};
+
+/// Generate a schema definition for a struct.
+pub fn get_struct_schema_def(
+    container_attrs: &NamedTypeOptions,
+    data_struct: DataStruct,
+    ident_span: Span,
+) -> Result<(TokenStream, TokenStream), Vec<syn::Error>> {
+    let mut record_field_exprs = vec![];
+    match data_struct.fields {
+        Fields::Named(a) => {
+            for field in a.named {
+                let mut name = field
+                    .ident
+                    .as_ref()
+                    .expect("Field must have a name")
+                    .to_string();
+                if let Some(raw_name) = name.strip_prefix("r#") {
+                    name = raw_name.to_string();
+                }
+                let field_attrs = FieldOptions::new(&field.attrs, 
field.span())?;
+                let doc = preserve_optional(field_attrs.doc);
+                match (field_attrs.rename, container_attrs.rename_all) {
+                    (Some(rename), _) => {
+                        name = rename;
+                    }
+                    (None, rename_all) if rename_all != RenameRule::None => {
+                        name = rename_all.apply_to_field(&name);
+                    }
+                    _ => {}
+                }
+                if field_attrs.skip {
+                    continue;
+                } else if field_attrs.flatten {
+                    // Inline the fields of the child record at runtime, as we 
don't have access to
+                    // the schema here.
+                    let get_record_fields = 
field_to_record_fields_expr(&field, field_attrs.with)?;
+                    record_field_exprs.push(quote! {
+                        if let Some(flattened_fields) = #get_record_fields {
+                            schema_fields.extend(flattened_fields);
+                        } else {
+                            panic!("{} does not have any fields to flatten 
to", stringify!(#field));
+                        }
+                    });
+
+                    // Don't add this field as it's been replaced by the child 
record fields
+                    continue;
+                }
+                let default_value = field_to_field_default_expr(&field, 
field_attrs.default)?;
+                let aliases = field_aliases(&field_attrs.alias);
+                let schema_expr = field_to_schema_expr(&field, 
field_attrs.with)?;
+                record_field_exprs.push(quote! {
+                    schema_fields.push(::apache_avro::schema::RecordField {
+                        name: #name.to_string(),
+                        doc: #doc,
+                        default: #default_value,
+                        aliases: #aliases,
+                        schema: #schema_expr,
+                        custom_attributes: ::std::collections::BTreeMap::new(),
+                    });
+                });
+            }
+        }
+        Fields::Unnamed(_) => {
+            return Err(vec![syn::Error::new(
+                ident_span,
+                "AvroSchema derive does not work for tuple structs",
+            )]);
+        }
+        Fields::Unit => {
+            return Err(vec![syn::Error::new(
+                ident_span,
+                "AvroSchema derive does not work for unit structs",
+            )]);
+        }
+    }
+
+    let record_doc = preserve_optional(container_attrs.doc.as_ref());
+    let record_aliases = aliases(&container_attrs.aliases);
+    let full_schema_name = &container_attrs.name;
+
+    // When flatten is involved, there will be more but we don't know how 
many. This optimises for
+    // the most common case where there is no flatten.
+    let minimum_fields = record_field_exprs.len();
+
+    let schema_def = quote! {
+        {
+            let mut schema_fields = 
::std::vec::Vec::with_capacity(#minimum_fields);
+            #(#record_field_exprs)*
+            let schema_field_set: ::std::collections::HashSet<_> = 
schema_fields.iter().map(|rf| &rf.name).collect();
+            assert_eq!(schema_fields.len(), schema_field_set.len(), "Duplicate 
field names found: {schema_fields:?}");
+            let name = 
::apache_avro::schema::Name::new(#full_schema_name).expect(&format!("Unable to 
parse struct name for schema {}", #full_schema_name)[..]);
+            let lookup: ::std::collections::BTreeMap<String, usize> = 
schema_fields
+                .iter()
+                .enumerate()
+                .map(|(position, field)| (field.name.to_owned(), position))
+                .collect();
+            
::apache_avro::schema::Schema::Record(::apache_avro::schema::RecordSchema {
+                name,
+                aliases: #record_aliases,
+                doc: #record_doc,
+                fields: schema_fields,
+                lookup,
+                attributes: ::std::collections::BTreeMap::new(),
+            })
+        }
+    };
+    let record_fields = quote! {
+        let mut schema_fields = 
::std::vec::Vec::with_capacity(#minimum_fields);
+        #(#record_field_exprs)*
+        ::std::option::Option::Some(schema_fields)
+    };
+
+    Ok((schema_def, record_fields))
+}
+
+/// Use the schema definition of the only field in the struct as the schema
+pub fn get_transparent_struct_schema_def(
+    fields: Fields,
+    input_span: Span,
+) -> Result<(TokenStream, TokenStream), Vec<syn::Error>> {
+    match fields {
+        Fields::Named(fields_named) => {
+            let mut found = None;
+            for field in fields_named.named {
+                let attrs = FieldOptions::new(&field.attrs, field.span())?;
+                if attrs.skip {
+                    continue;
+                }
+                if found.replace((field, attrs)).is_some() {
+                    return Err(vec![syn::Error::new(
+                        input_span,
+                        "AvroSchema: #[serde(transparent)] is only allowed on 
structs with one unskipped field",
+                    )]);
+                }
+            }
+
+            if let Some((field, attrs)) = found {
+                Ok((
+                    field_to_schema_expr(&field, attrs.with.clone())?,
+                    field_to_record_fields_expr(&field, attrs.with)?,
+                ))
+            } else {
+                Err(vec![syn::Error::new(
+                    input_span,
+                    "AvroSchema: #[serde(transparent)] is only allowed on 
structs with one unskipped field",
+                )])
+            }
+        }
+        Fields::Unnamed(_) => Err(vec![syn::Error::new(
+            input_span,
+            "AvroSchema: derive does not work for tuple structs",
+        )]),
+        Fields::Unit => Err(vec![syn::Error::new(
+            input_span,
+            "AvroSchema: derive does not work for unit structs",
+        )]),
+    }
+}
diff --git a/avro_derive/src/utils.rs b/avro_derive/src/utils.rs
new file mode 100644
index 0000000..6affff0
--- /dev/null
+++ b/avro_derive/src/utils.rs
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use proc_macro2::TokenStream;
+use quote::quote;
+
+/// Convert a list of errors into actual compiler errors.
+///
+/// Copied from `serde`, originally written by David Tolnay.
+pub fn to_compile_errors(errors: impl AsRef<[syn::Error]>) -> TokenStream {
+    let compile_errors = 
errors.as_ref().iter().map(syn::Error::to_compile_error);
+    quote!(#(#compile_errors)*)
+}
+
+pub fn preserve_optional(op: Option<impl quote::ToTokens>) -> TokenStream {
+    if let Some(tt) = op {
+        quote! {::std::option::Option::Some(#tt.into())}
+    } else {
+        quote! {::std::option::Option::None}
+    }
+}
+
+/// Convert a list of strings to an expression that resolves to a 
`Option<Vec<Alias>>`.
+pub fn aliases(op: &[impl AsRef<str>]) -> TokenStream {
+    let items: Vec<TokenStream> = op
+        .iter()
+        .map(|alias| {
+            let alias = alias.as_ref();
+            quote! {
+                ::apache_avro::schema::Alias::new(#alias).expect("Alias is 
invalid")
+            }
+        })
+        .collect();
+    if items.is_empty() {
+        quote! {::std::option::Option::None}
+    } else {
+        quote! {::std::option::Option::Some(vec![#(#items),*])}
+    }
+}
+
+/// Convert a list of strings to an expression that resolves to a 
`Vec<String>`.
+pub fn field_aliases(op: &[impl AsRef<str>]) -> TokenStream {
+    let items: Vec<TokenStream> = op
+        .iter()
+        .map(|string| {
+            let string = string.as_ref();
+            quote! {
+                ::std::string::String::from(#string)
+            }
+        })
+        .collect();
+    quote! {vec![#(#items),*]}
+}
diff --git 
a/avro_derive/tests/expanded/avro_3709_record_field_attributes.expanded.rs 
b/avro_derive/tests/expanded/avro_3709_record_field_attributes.expanded.rs
index 0d35f4b..e228d8c 100644
--- a/avro_derive/tests/expanded/avro_3709_record_field_attributes.expanded.rs
+++ b/avro_derive/tests/expanded/avro_3709_record_field_attributes.expanded.rs
@@ -31,14 +31,16 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         doc: ::std::option::Option::Some("a doc".into()),
                         default: ::std::option::Option::Some(
                             ::serde_json::from_str("123")
-                                .expect("Unreachable! This parsed at compile 
time!"),
+                                .expect(
+                                    "Unreachable! This parsed successfully at 
compile time!",
+                                ),
                         ),
                         aliases: 
::alloc::boxed::box_assume_init_into_vec_unsafe(
                             ::alloc::intrinsics::write_box_via_move(
                                 ::alloc::boxed::Box::new_uninit(),
                                 [
-                                    "a1".try_into().expect("Alias is invalid"),
-                                    "a2".try_into().expect("Alias is invalid"),
+                                    ::std::string::String::from("a1"),
+                                    ::std::string::String::from("a2"),
                                 ],
                             ),
                         ),
@@ -106,14 +108,14 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 doc: ::std::option::Option::Some("a doc".into()),
                 default: ::std::option::Option::Some(
                     ::serde_json::from_str("123")
-                        .expect("Unreachable! This parsed at compile time!"),
+                        .expect("Unreachable! This parsed successfully at 
compile time!"),
                 ),
                 aliases: ::alloc::boxed::box_assume_init_into_vec_unsafe(
                     ::alloc::intrinsics::write_box_via_move(
                         ::alloc::boxed::Box::new_uninit(),
                         [
-                            "a1".try_into().expect("Alias is invalid"),
-                            "a2".try_into().expect("Alias is invalid"),
+                            ::std::string::String::from("a1"),
+                            ::std::string::String::from("a2"),
                         ],
                     ),
                 ),
diff --git 
a/avro_derive/tests/expanded/avro_rs_207_rename_all_attribute.expanded.rs 
b/avro_derive/tests/expanded/avro_rs_207_rename_all_attribute.expanded.rs
index d80a114..f13c46c 100644
--- a/avro_derive/tests/expanded/avro_rs_207_rename_all_attribute.expanded.rs
+++ b/avro_derive/tests/expanded/avro_rs_207_rename_all_attribute.expanded.rs
@@ -29,7 +29,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "ITEM".to_string(),
                         doc: ::std::option::Option::None,
                         default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -41,7 +41,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "DOUBLE_ITEM".to_string(),
                         doc: ::std::option::Option::None,
                         default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -105,7 +105,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "ITEM".to_string(),
                 doc: ::std::option::Option::None,
                 default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
@@ -117,7 +117,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "DOUBLE_ITEM".to_string(),
                 doc: ::std::option::Option::None,
                 default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
diff --git 
a/avro_derive/tests/expanded/avro_rs_207_rename_attr_over_rename_all_attribute.expanded.rs
 
b/avro_derive/tests/expanded/avro_rs_207_rename_attr_over_rename_all_attribute.expanded.rs
index 0689cb1..c26134c 100644
--- 
a/avro_derive/tests/expanded/avro_rs_207_rename_attr_over_rename_all_attribute.expanded.rs
+++ 
b/avro_derive/tests/expanded/avro_rs_207_rename_attr_over_rename_all_attribute.expanded.rs
@@ -30,7 +30,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "ITEM".to_string(),
                         doc: ::std::option::Option::None,
                         default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -42,7 +42,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "DoubleItem".to_string(),
                         doc: ::std::option::Option::None,
                         default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -106,7 +106,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "ITEM".to_string(),
                 doc: ::std::option::Option::None,
                 default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
@@ -118,7 +118,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "DoubleItem".to_string(),
                 doc: ::std::option::Option::None,
                 default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
diff --git a/avro_derive/tests/expanded/avro_rs_501_basic.expanded.rs 
b/avro_derive/tests/expanded/avro_rs_501_basic.expanded.rs
index 34576a5..3562a9b 100644
--- a/avro_derive/tests/expanded/avro_rs_501_basic.expanded.rs
+++ b/avro_derive/tests/expanded/avro_rs_501_basic.expanded.rs
@@ -28,7 +28,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "a".to_string(),
                         doc: ::std::option::Option::None,
                         default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -40,7 +40,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "b".to_string(),
                         doc: ::std::option::Option::None,
                         default: <String as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <String as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -104,7 +104,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "a".to_string(),
                 doc: ::std::option::Option::None,
                 default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
@@ -116,7 +116,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "b".to_string(),
                 doc: ::std::option::Option::None,
                 default: <String as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <String as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
diff --git a/avro_derive/tests/expanded/avro_rs_501_namespace.expanded.rs 
b/avro_derive/tests/expanded/avro_rs_501_namespace.expanded.rs
index ce84a5d..947173b 100644
--- a/avro_derive/tests/expanded/avro_rs_501_namespace.expanded.rs
+++ b/avro_derive/tests/expanded/avro_rs_501_namespace.expanded.rs
@@ -29,7 +29,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "a".to_string(),
                         doc: ::std::option::Option::None,
                         default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -41,7 +41,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                         name: "b".to_string(),
                         doc: ::std::option::Option::None,
                         default: <String as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <String as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -106,7 +106,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "a".to_string(),
                 doc: ::std::option::Option::None,
                 default: <i32 as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <i32 as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
@@ -118,7 +118,7 @@ impl ::apache_avro::AvroSchemaComponent for A {
                 name: "b".to_string(),
                 doc: ::std::option::Option::None,
                 default: <String as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <String as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
diff --git a/avro_derive/tests/expanded/avro_rs_501_reference.expanded.rs 
b/avro_derive/tests/expanded/avro_rs_501_reference.expanded.rs
index 9916d4f..a7e9293 100644
--- a/avro_derive/tests/expanded/avro_rs_501_reference.expanded.rs
+++ b/avro_derive/tests/expanded/avro_rs_501_reference.expanded.rs
@@ -30,7 +30,7 @@ impl<'a> ::apache_avro::AvroSchemaComponent for A<'a> {
                         default: <&'a Vec<
                             i32,
                         > as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <&'a Vec<
                             i32,
                         > as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
@@ -44,7 +44,7 @@ impl<'a> ::apache_avro::AvroSchemaComponent for A<'a> {
                         name: "b".to_string(),
                         doc: ::std::option::Option::None,
                         default: <&'static str as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <&'static str as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                             named_schemas,
                             enclosing_namespace,
@@ -110,7 +110,7 @@ impl<'a> ::apache_avro::AvroSchemaComponent for A<'a> {
                 default: <&'a Vec<
                     i32,
                 > as ::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <&'a Vec<
                     i32,
                 > as ::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
@@ -124,7 +124,7 @@ impl<'a> ::apache_avro::AvroSchemaComponent for A<'a> {
                 name: "b".to_string(),
                 doc: ::std::option::Option::None,
                 default: <&'static str as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <&'static str as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
                     named_schemas,
                     enclosing_namespace,
diff --git 
a/avro_derive/tests/expanded/avro_rs_501_struct_with_optional.expanded.rs 
b/avro_derive/tests/expanded/avro_rs_501_struct_with_optional.expanded.rs
index 076143e..e199f7c 100644
--- a/avro_derive/tests/expanded/avro_rs_501_struct_with_optional.expanded.rs
+++ b/avro_derive/tests/expanded/avro_rs_501_struct_with_optional.expanded.rs
@@ -29,7 +29,7 @@ impl ::apache_avro::AvroSchemaComponent for TestOptional {
                         default: <Option<
                             i32,
                         > as 
::apache_avro::AvroSchemaComponent>::field_default(),
-                        aliases: ::std::vec::Vec::new(),
+                        aliases: ::alloc::vec::Vec::new(),
                         schema: <Option<
                             i32,
                         > as 
::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
@@ -98,7 +98,7 @@ impl ::apache_avro::AvroSchemaComponent for TestOptional {
                 default: <Option<
                     i32,
                 > as ::apache_avro::AvroSchemaComponent>::field_default(),
-                aliases: ::std::vec::Vec::new(),
+                aliases: ::alloc::vec::Vec::new(),
                 schema: <Option<
                     i32,
                 > as ::apache_avro::AvroSchemaComponent>::get_schema_in_ctxt(
diff --git a/avro_derive/tests/ui/avro_rs_397_with_expr_string.stderr 
b/avro_derive/tests/ui/avro_rs_397_with_expr_string.stderr
index 9107607..1b150c4 100644
--- a/avro_derive/tests/ui/avro_rs_397_with_expr_string.stderr
+++ b/avro_derive/tests/ui/avro_rs_397_with_expr_string.stderr
@@ -1,4 +1,4 @@
-error: Invalid expression, expected function or closure
+error: Invalid expression, expected a function or a closure
   --> tests/ui/avro_rs_397_with_expr_string.rs:22:5
    |
 22 | /     #[avro(with = "Schema::Bytes")]

Reply via email to