# Task: Implementation Details for Lifetime-Only Structs Fix
## Detailed Code Changes Required
### 1. Current Problem Areas in former_struct.rs
#### Problem 1: Former Type Reference
```rust
// Current (line ~195):
let former_type_ref_generics = build_generics_with_params(
&struct_generics_impl_without_lifetimes,
&[parse_quote! { Definition }],
);
```
When `struct_generics_impl_without_lifetimes` is empty (lifetime-only struct), this creates `<Definition>` which is correct, but other code expects type parameters before Definition.
#### Problem 2: EntityToFormer Implementation
```rust
// Current pattern that fails:
impl< #entity_to_former_impl_generics > former::EntityToFormer< Definition >
for #struct_type_ref
```
When struct has only lifetimes, `entity_to_former_impl_generics` becomes `<'a, Definition>` which is valid, but the trait expects the implementing type to have matching type parameters.
### 2. Proposed Solutions
#### Solution Approach 1: Conditional Code Generation
```rust
// In former_struct function, after decomposing generics:
let has_only_lifetimes = struct_generics_impl.iter()
.all(|param| matches!(param, syn::GenericParam::Lifetime(_)));
let has_type_params = struct_generics_impl.iter()
.any(|param| matches!(param, syn::GenericParam::Type(_) | syn::GenericParam::Const(_)));
// Generate different patterns based on generic types
let entity_to_former_impl = if has_only_lifetimes {
// Special case for lifetime-only
quote! {
impl< #struct_generics_impl, Definition > former::EntityToFormer< Definition >
for #struct_type_ref
where
Definition : former::FormerDefinition< Storage = #storage_type_ref >,
Definition::Types : former::FormerDefinitionTypes< Storage = #storage_type_ref, Formed = #struct_type_ref >,
}
} else {
// Current implementation
quote! {
impl< #entity_to_former_impl_generics > former::EntityToFormer< Definition >
for #struct_type_ref
where
Definition : former::FormerDefinition< Storage = #storage_type_ref >,
Definition::Types : former::FormerDefinitionTypes< Storage = #storage_type_ref, Formed = #struct_type_ref >,
}
};
```
#### Solution Approach 2: Fix Generic List Building
Modify `build_generics_with_params` to handle lifetime-only cases:
```rust
fn build_generics_with_params(
base_generics: &syn::punctuated::Punctuated<syn::GenericParam, syn::token::Comma>,
additional_params: &[syn::GenericParam],
) -> syn::punctuated::Punctuated<syn::GenericParam, syn::token::Comma> {
let mut result = syn::punctuated::Punctuated::new();
// Add all parameters from base, maintaining order
for param in base_generics.iter() {
result.push_value(param.clone());
}
// Add comma only if we have both base and additional params
if !result.is_empty() && !additional_params.is_empty() {
result.push_punct(syn::token::Comma::default());
}
// Add additional params
for (i, param) in additional_params.iter().enumerate() {
result.push_value(param.clone());
if i < additional_params.len() - 1 {
result.push_punct(syn::token::Comma::default());
}
}
result
}
```
### 3. Specific Areas to Fix
#### Area 1: Storage Structure Generation
```rust
// Current generates: SimpleFormerStorage<'a,>
// Should generate: SimpleFormerStorage<'a>
#[derive(Debug)]
pub struct #former_storage < #struct_generics_with_defaults >
#struct_generics_where
{
#(#fields),*
}
```
#### Area 2: Former Structure Generation
```rust
// Need to handle: SimpleFormer<'a, Definition> vs SimpleFormer<Definition>
// Solution: Always include lifetimes in Former struct
pub struct #former < #struct_generics_impl, Definition = #former_definition < #former_definition_args > >
where
Definition : former::FormerDefinition< Storage = #storage_type_ref >,
{
// fields...
}
```
#### Area 3: Method Implementations
```rust
// EntityToFormer, EntityToDefinition, etc need proper generic handling
// Each needs conditional generation based on has_only_lifetimes
```
### 4. Test Scenarios to Cover
1. **Simple lifetime struct**:
```rust
struct Simple<'a> {
data: &'a str,
}
```
2. **Multiple lifetimes**:
```rust
struct Multiple<'a, 'b> {
first: &'a str,
second: &'b str,
}
```
3. **Lifetime with bounds**:
```rust
struct Bounded<'a: 'b, 'b> {
data: &'a str,
reference: &'b str,
}
```
4. **Mixed generics** (ensure no regression):
```rust
struct Mixed<'a, T> {
data: &'a str,
value: T,
}
```
### 5. Implementation Order
1. First, add detection for lifetime-only generics
2. Update `build_generics_with_params` to handle empty base with lifetimes
3. Fix storage struct generation
4. Fix former struct generation
5. Fix all impl blocks one by one
6. Add comprehensive tests
7. Re-enable disabled lifetime tests
### 6. Validation Steps
1. Run existing tests to ensure no regression
2. Enable and run lifetime-only struct tests
3. Check generated code with `#[debug]` attribute
4. Test with various combinations of generics
5. Verify error messages are clear when things fail