former 2.42.0

A flexible implementation of the Builder pattern supporting nested builders and collection-specific subformers. Simplify the construction of complex objects.
Documentation
# Former Macro: Architectural Limitations Analysis

This document provides a systematic analysis of the fundamental limitations preventing certain patterns from working with the Former crate. Each limitation is **experimentally verified** and includes workarounds where available.

## Quick Decision Tree: Will Former Work For My Use Case?

```
START: Want to use #[derive(Former)]
  │
  ├─ Do you need borrowed data (&'a T)?
  │  ├─ YES ─> ❌ Won't work (Lifetime Limitation)
  │  │         Workaround: Use Arc<T>, Cow<'static, T>, or owned types
  │  └─ NO ──> Continue ↓
  │
  ├─ Is your type an enum with generic parameters?
  │  ├─ YES ─> ❌ Won't work (Generic Enum Limitation)
  │  │         Workaround: Use concrete types (String instead of T)
  │  └─ NO ──> Continue ↓
  │
  ├─ Is your enum multi-variant with complex patterns?
  │  ├─ YES ─> ⚠️ May conflict (Trait Conflict Limitation)
  │  │         Workaround: Use single-variant enums or split types
  │  └─ NO ──> Continue ↓
  │
  └─> ✅ Former should work! Proceed with confidence.
```

## Workaround Quick Reference

| Limitation | Won't Work | Use Instead |
|------------|------------|-------------|
| **Lifetimes** | `field: &'a str` | `field: String` or `field: Arc<str>` |
| **Lifetimes** | `field: &'a [u8]` | `field: Vec<u8>` or `field: Bytes` |
| **Lifetimes** | `headers: &'a HeaderMap` | `headers: Arc<HeaderMap>` |
| **Generic Enums** | `enum Msg<T> { Val(T) }` | `enum Msg { Val(String) }` |
| **Multi-Variant** | Complex enum with 5+ variants | Split into separate enums or use single variant |

---

## Detailed Analysis

This document provides a systematic analysis of the 4 fundamental limitations preventing certain tests from being enabled in the Former crate. Each limitation is **experimentally verified** and characterized using the Target Type Classification framework from the specification.

## Target Type Classification Context

According to the Former specification, the macro operates on two fundamental **Target Type Categories**:
- **Structs** - Regular Rust structs with named fields
- **Enums** - Rust enums with variants, subdivided by **Variant Structure Types** (Unit, Tuple, Named)

Each limitation affects these target types differently, as detailed in the analysis below.

## 1. Generic Enum Parsing Limitation ✅ TESTED

### Limitation Characteristics
- **Scope**: Enum Target Type Category only (Structs unaffected)
- **Severity**: Complete blocking - no generic enums supported
- **Behavioral Categories Affected**: All enum formers (Unit/Tuple/Named Variant Formers)
- **Variant Structure Types Affected**: All (Unit, Tuple, Named variants)
- **Root Cause**: Macro parser architecture limitation
- **Workaround Availability**: Full (concrete type replacement)
- **Future Compatibility**: Possible (requires major rewrite)

**What it means**: The macro cannot parse generic parameter syntax in enum declarations.

### ❌ This Breaks:
```rust
#[derive(Former)]
pub enum GenericEnum<T> {  // <-- The <T> part breaks the macro
    Variant(T),
}
```
**Verified Error**: `expected '::' found '>'` - macro parser fails on generic syntax

### ✅ This Works:
```rust
#[derive(Former)]
pub enum ConcreteEnum {  // <-- No <T>, so it works
    Variant(String),
}
// Usage: ConcreteEnum::variant()._0("hello".to_string()).form()
```

**The Technical Choice**: Simple token-based parser vs Full AST parser with generics

**Trade-off Details**:
- **Current approach**: Fast compilation, simple implementation
- **Alternative approach**: Slow compilation, complex parser supporting generics
- **Implementation cost**: Complete macro rewrite with full Rust AST parsing
- **Performance impact**: Significant compilation time increase

**Can Both Be Combined?** 🟡 **PARTIALLY**
- Technically possible but requires rewriting the entire macro parser
- Would need full Rust AST parsing instead of simple token matching
- Trade-off: Fast builds vs Generic enum support

---

## 2. Lifetime Constraint Limitation ✅ VERIFIED IN CODE

### Limitation Characteristics
- **Scope**: Both Target Type Categories (Structs and Enums)
- **Severity**: Fundamental blocking - no lifetime parameters supported
- **Behavioral Categories Affected**: All Former types with lifetime parameters
- **Variant Structure Types Affected**: N/A (applies to type-level generics)
- **Root Cause**: Rust language constraint (trait objects + lifetimes)
- **Workaround Availability**: Partial (owned data only)
- **Future Compatibility**: Impossible (fundamental Rust limitation)

**What it means**: Rust's memory safety rules fundamentally prevent borrowed data in Former storage due to trait object lifetime requirements.

### ❌ This Breaks:
```rust
// From parametrized_dyn_manual.rs:210 - real example
impl<'callback> StoragePreform for StylesFormerStorage<'callback> {
    fn preform(self) -> Self::Preformed {
        // ERROR E0521: borrowed data escapes outside of method
        (&PhantomData::<&'callback dyn FilterCol>).maybe_default()
        // `'callback` must outlive `'static`
    }
}
```

### ✅ This Works:
```rust
#[derive(Former)]
pub struct OwnedStruct {
    owned_data: String,         // <-- Owned data is fine
    numbers: Vec<i32>,          // <-- Owned collections work
    static_ref: &'static str    // <-- Static references work
}
```

**The Technical Choice**: Trait object compatibility with memory safety vs Complex lifetime support

**Trade-off Details**:
- **Current approach**: Memory safety + trait objects work reliably
- **Alternative approach**: Complex lifetime tracking in all generated code
- **Fundamental constraint**: Trait objects require `'static` bounds for type erasure
- **Rust limitation**: Cannot allow borrowed data to escape method boundaries

**Can Both Be Combined?** 🔴 **NO**
- This is a hard Rust language constraint, not our design choice
- Trait objects fundamentally require `'static` bounds
- Even perfect implementation cannot overcome Rust's type system rules

---

## 3. Trait Conflict Limitation ✅ TESTED

### Limitation Characteristics
- **Scope**: Enum Target Type Category only (multi-variant enums)
- **Severity**: Selective blocking - single-variant enums work fine
- **Behavioral Categories Affected**: Mixed enum scenarios (Complex Scenario Formers)
- **Variant Structure Types Affected**: All when combined in single enum
- **Root Cause**: Duplicate trait implementation generation
- **Workaround Availability**: Full (single variant per enum)
- **Future Compatibility**: Possible (requires complex deduplication logic)

**What it means**: The macro generates conflicting trait implementations when multiple enum variants require the same traits.

### ❌ This Breaks:
```rust
#[derive(Former)]
pub enum MultiVariantEnum {
    VariantA { field: String },  // <-- Each variant tries to
    VariantB { other: i32 },     // <-- generate the same traits
    VariantC,                    // <-- causing conflicts
}
```
**Verified Error E0119**: `conflicting implementations of trait EntityToStorage`

### ✅ This Works:
```rust
#[derive(Former)]
pub enum SingleVariantEnum {
    OnlyVariant { field: String },  // <-- One variant = no conflicts
}
// Usage: SingleVariantEnum::only_variant().field("test".to_string()).form()
```

**The Technical Choice**: Simple per-enum trait generation vs Complex trait deduplication

**Trade-off Details**:
- **Current approach**: Simple code generation, one trait impl per enum
- **Alternative approach**: Sophisticated trait deduplication with variant-specific logic
- **Implementation complexity**: Exponential increase in generated code complexity
- **Maintenance burden**: Much harder to debug and maintain complex generation

**Can Both Be Combined?** 🟡 **YES, BUT VERY COMPLEX**
- Technically possible with sophisticated trait merging logic
- Requires tracking implementations across all variants
- Major increase in macro complexity and maintenance burden
- Cost/benefit analysis favors current simple approach

---

## Comprehensive Limitations Matrix

| Limitation | Target Type Scope | Severity Level | Behavioral Categories | Future Fix | Workaround | Decision Impact |
|------------|------------------|----------------|----------------------|-----------|------------|----------------|
| **Generic Parsing** | Enums only | Complete blocking | All enum formers | 🟡 Possible (major rewrite) | ✅ Concrete types | High - affects API design |
| **Lifetime Constraints** | Structs + Enums | Fundamental blocking | All with lifetimes | 🔴 Impossible (Rust constraint) | 🟡 Owned data only | Critical - shapes data patterns |
| **Trait Conflicts** | Multi-variant enums | Selective blocking | Complex scenarios | 🟡 Possible (complex logic) | ✅ Single variants | Medium - affects enum design |

### Key Decision-Making Insights

**Architectural Impact Ranking**:
1. **Lifetime Constraints** - Most critical, shapes fundamental data patterns
2. **Generic Parsing** - High impact on API flexibility and user experience
3. **Trait Conflicts** - Medium impact, affects complex enum design strategies
4. **Compile-fail Tests** - Low impact, testing methodology only

**Workaround Effectiveness**:
- **Full workarounds available**: Generic Parsing, Trait Conflicts
- 🟡 **Partial workarounds**: Lifetime Constraints (owned data patterns)
-**No workarounds needed**: Compile-fail Tests (working as intended)

**Engineering Trade-offs**:
- **Generic Parsing**: Simple parser vs Universal enum support
- **Lifetime Constraints**: Memory safety vs Flexible borrowing patterns
- **Trait Conflicts**: Simple generation vs Complex multi-variant enums
- **Compile-fail Tests**: Error validation vs Maximum passing test count