Repository: bevyengine/bevy
File: crates/bevy_ecs/macros/src/component.rs (Rust)

Code before:
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{format_ident, quote, ToTokens};
use std::collections::HashSet;
use syn::{
    braced, parenthesized,
    parse::Parse,
    parse_macro_input, parse_quote,
    punctuated::Punctuated,
    spanned::Spanned,
    token::{Brace, Comma, Paren},
    Data, DataEnum, DataStruct, DeriveInput, Expr, ExprCall, ExprPath, Field, Fields, Ident,
    LitStr, Member, Path, Result, Token, Type, Visibility,
};

pub fn derive_resource(input: TokenStream) -> TokenStream {
    let mut ast = parse_macro_input!(input as DeriveInput);
    let bevy_ecs_path: Path = crate::bevy_ecs_path();

    // We want to raise a compile time error when the generic lifetimes
    // are not bound to 'static lifetime
    let non_static_lifetime_error: Option<syn::Error> = ast
        .generics
        .lifetimes()
        .filter(|lifetime| !lifetime.bounds.iter().any(|bound| bound.ident == "static"))
        .map(|param| syn::Error::new(param.span(), "Lifetimes must be 'static"))
        .reduce(|mut err_acc, err| {
            err_acc.combine(err);
            err_acc
        });
    if let Some(err) = non_static_lifetime_error {
        return err.into_compile_error().into();
    }

    ast.generics
        .make_where_clause()
        .predicates
        .push(parse_quote! { Self: Send + Sync + 'static });

    let struct_name = &ast.ident;
    let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

    TokenStream::from(quote! {
        impl #impl_generics #bevy_ecs_path::resource::Resource for #struct_name #type_generics #where_clause {
        }
    })
}

Review comment (suggestion):
I think this type can be inferred:

```suggestion
    let non_static_lifetime_error = ast
```

Code after:
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{format_ident, quote, ToTokens};
use std::collections::HashSet;
use syn::{
    braced, parenthesized,
    parse::Parse,
    parse_macro_input, parse_quote,
    punctuated::Punctuated,
    spanned::Spanned,
    token::{Brace, Comma, Paren},
    Data, DataEnum, DataStruct, DeriveInput, Expr, ExprCall, ExprPath, Field, Fields, Ident,
    LitStr, Member, Path, Result, Token, Type, Visibility,
};

pub fn derive_resource(input: TokenStream) -> TokenStream {
    let mut ast = parse_macro_input!(input as DeriveInput);
    let bevy_ecs_path: Path = crate::bevy_ecs_path();

    // We want to raise a compile time error when the generic lifetimes
    // are not bound to 'static lifetime
    let non_static_lifetime_error = ast
        .generics
        .lifetimes()
        .filter(|lifetime| !lifetime.bounds.iter().any(|bound| bound.ident == "static"))
        .map(|param| syn::Error::new(param.span(), "Lifetimes must be 'static"))
        .reduce(|mut err_acc, err| {
            err_acc.combine(err);
            err_acc
        });
    if let Some(err) = non_static_lifetime_error {
        return err.into_compile_error().into();
    }

    ast.generics
        .make_where_clause()
        .predicates
        .push(parse_quote! { Self: Send + Sync + 'static });

    let struct_name = &ast.ident;
    let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

    TokenStream::from(quote! {
        impl #impl_generics #bevy_ecs_path::resource::Resource for #struct_name #type_generics #where_clause {
        }
    })
}