 7a72bac779
			
		
	
	
		7a72bac779
		
			
		
	
	
	
	
		
			
			# Objective Fix #9960 ## Solution Make the `visit` parameter `_visit` if there are no dependencies. New `cargo expand` output: ```rust pub struct Rarity { pub name: SharedStr, pub color: Color, } impl bevy::asset::Asset for Rarity {} impl bevy::asset::VisitAssetDependencies for Rarity { fn visit_dependencies( &self, _visit: &mut impl FnMut(bevy::asset::UntypedAssetId), // <-- fixed ) {} } impl bevy::reflect::TypePath for Rarity { fn type_path() -> &'static str { "myasset::item::Rarity" } fn short_type_path() -> &'static str { "Rarity" } fn type_ident() -> Option<&'static str> { ::core::option::Option::Some("Rarity") } fn crate_name() -> Option<&'static str> { ::core::option::Option::Some( "myasset::item".split(':').next().unwrap(), ) } fn module_path() -> Option<&'static str> { ::core::option::Option::Some("myasset::item") } } ```
		
			
				
	
	
		
			84 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use bevy_macro_utils::BevyManifest;
 | |
| use proc_macro::{Span, TokenStream};
 | |
| use quote::quote;
 | |
| use syn::{parse_macro_input, Data, DeriveInput, Path};
 | |
| 
 | |
| pub(crate) fn bevy_asset_path() -> syn::Path {
 | |
|     BevyManifest::default().get_path("bevy_asset")
 | |
| }
 | |
| 
 | |
| const DEPENDENCY_ATTRIBUTE: &str = "dependency";
 | |
| 
 | |
| #[proc_macro_derive(Asset, attributes(dependency))]
 | |
| pub fn derive_asset(input: TokenStream) -> TokenStream {
 | |
|     let ast = parse_macro_input!(input as DeriveInput);
 | |
|     let bevy_asset_path: Path = bevy_asset_path();
 | |
| 
 | |
|     let struct_name = &ast.ident;
 | |
|     let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
 | |
|     let dependency_visitor = match derive_dependency_visitor_internal(&ast, &bevy_asset_path) {
 | |
|         Ok(dependency_visitor) => dependency_visitor,
 | |
|         Err(err) => return err.into_compile_error().into(),
 | |
|     };
 | |
| 
 | |
|     TokenStream::from(quote! {
 | |
|         impl #impl_generics #bevy_asset_path::Asset for #struct_name #type_generics #where_clause { }
 | |
|         #dependency_visitor
 | |
|     })
 | |
| }
 | |
| 
 | |
| #[proc_macro_derive(VisitAssetDependencies, attributes(dependency))]
 | |
| pub fn derive_asset_dependency_visitor(input: TokenStream) -> TokenStream {
 | |
|     let ast = parse_macro_input!(input as DeriveInput);
 | |
|     let bevy_asset_path: Path = bevy_asset_path();
 | |
|     match derive_dependency_visitor_internal(&ast, &bevy_asset_path) {
 | |
|         Ok(dependency_visitor) => TokenStream::from(dependency_visitor),
 | |
|         Err(err) => err.into_compile_error().into(),
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn derive_dependency_visitor_internal(
 | |
|     ast: &DeriveInput,
 | |
|     bevy_asset_path: &Path,
 | |
| ) -> Result<proc_macro2::TokenStream, syn::Error> {
 | |
|     let mut field_visitors = Vec::new();
 | |
|     if let Data::Struct(data_struct) = &ast.data {
 | |
|         for field in &data_struct.fields {
 | |
|             if field
 | |
|                 .attrs
 | |
|                 .iter()
 | |
|                 .any(|a| a.path().is_ident(DEPENDENCY_ATTRIBUTE))
 | |
|             {
 | |
|                 if let Some(field_ident) = &field.ident {
 | |
|                     field_visitors.push(quote! {
 | |
|                         #bevy_asset_path::VisitAssetDependencies::visit_dependencies(&self.#field_ident, visit);
 | |
|                     });
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     } else {
 | |
|         return Err(syn::Error::new(
 | |
|             Span::call_site().into(),
 | |
|             "Asset derive currently only works on structs",
 | |
|         ));
 | |
|     }
 | |
| 
 | |
|     let struct_name = &ast.ident;
 | |
|     let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
 | |
| 
 | |
|     // prevent unused variable warning in case there are no dependencies
 | |
|     let visit = if field_visitors.is_empty() {
 | |
|         quote! { _visit }
 | |
|     } else {
 | |
|         quote! { visit }
 | |
|     };
 | |
| 
 | |
|     Ok(quote! {
 | |
|         impl #impl_generics #bevy_asset_path::VisitAssetDependencies for #struct_name #type_generics #where_clause {
 | |
|             fn visit_dependencies(&self, #visit: &mut impl FnMut(#bevy_asset_path::UntypedAssetId)) {
 | |
|                 #(#field_visitors)*
 | |
|             }
 | |
|         }
 | |
|     })
 | |
| }
 |