fix generics for relationships (#18136)

# Objective
Allow Relationship to be derived for structs with generics.

fixes #18133
## Solution

"X" inside #[relationship_target(relationship = X)] was previously
parsed as Idents,
now they are parsed as syn::Type

## Testing

```rust
#[derive(Component)]
#[relationship(relationship_target = Attachments<T>)]
pub struct AttachedTo<T: Send + Sync + 'static> {
    #[relationship]
    pub entity: Entity,
    pub marker: PhantomData<T>,
}

#[derive(Component)]
#[relationship_target(relationship = AttachedTo<T>)]
pub struct Attachments<T: Send + Sync + 'static> {
    #[relationship]
    entities: Vec<Entity>,
    pub marker: PhantomData<T>,
}
```
This now compiles!
This commit is contained in:
Tim Overbeek 2025-03-03 20:33:29 +01:00 committed by GitHub
parent 236091adce
commit 173680944f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -10,7 +10,7 @@ use syn::{
spanned::Spanned,
token::{Comma, Paren},
Data, DataStruct, DeriveInput, ExprClosure, ExprPath, Field, Fields, Ident, Index, LitStr,
Member, Path, Result, Token, Visibility,
Member, Path, Result, Token, Type, Visibility,
};
pub fn derive_event(input: TokenStream) -> TokenStream {
@ -474,11 +474,11 @@ enum RequireFunc {
}
struct Relationship {
relationship_target: Ident,
relationship_target: Type,
}
struct RelationshipTarget {
relationship: Ident,
relationship: Type,
linked_spawn: bool,
}
@ -613,14 +613,14 @@ impl Parse for Relationship {
input.parse::<relationship_target>()?;
input.parse::<Token![=]>()?;
Ok(Relationship {
relationship_target: input.parse::<Ident>()?,
relationship_target: input.parse::<Type>()?,
})
}
}
impl Parse for RelationshipTarget {
fn parse(input: syn::parse::ParseStream) -> Result<Self> {
let mut relationship_ident = None;
let mut relationship_type: Option<Type> = None;
let mut linked_spawn_exists = false;
syn::custom_keyword!(relationship);
syn::custom_keyword!(linked_spawn);
@ -629,7 +629,7 @@ impl Parse for RelationshipTarget {
if input.peek(relationship) {
input.parse::<relationship>()?;
input.parse::<Token![=]>()?;
relationship_ident = Some(input.parse::<Ident>()?);
relationship_type = Some(input.parse()?);
} else if input.peek(linked_spawn) {
input.parse::<linked_spawn>()?;
linked_spawn_exists = true;
@ -644,7 +644,7 @@ impl Parse for RelationshipTarget {
}
}
let relationship = relationship_ident.ok_or_else(|| syn::Error::new(input.span(), "RelationshipTarget derive must specify a relationship via #[relationship_target(relationship = X)"))?;
let relationship = relationship_type.ok_or_else(|| syn::Error::new(input.span(), "RelationshipTarget derive must specify a relationship via #[relationship_target(relationship = X)"))?;
Ok(RelationshipTarget {
relationship,
linked_spawn: linked_spawn_exists,