-
-
Notifications
You must be signed in to change notification settings - Fork 1
Closed
Labels
area:coreCore compiler (parser, generator, IR, transform)Core compiler (parser, generator, IR, transform)type:enhancementImprovement to existing featureImprovement to existing featuretype:featureNew feature or functionalityNew feature or functionality
Description
Goal
Support generic type parameters on structs and enums for reusable, type-safe containers.
Phase: 5.3 Advanced Type System
Problem
Current limitations:
- ❌ Can't create generic containers like
Box<T>,Wrapper<T> - ❌ Code duplication for similar types
- ❌ Can't match Rust's generic patterns
- ❌ Limited reusability
Solution
Add generic type parameters to struct and enum definitions.
Syntax
// Generic struct
struct Wrapper<T> {
value: T,
}
// Generic enum
enum Result<T, E> {
Ok(T),
Err(E),
}
// Multiple type parameters
struct Pair<A, B> {
first: A,
second: B,
}
Usage
struct PlayerData {
name: String,
level: u16,
}
struct GameState {
player: Wrapper<PlayerData>, // Wrapper<PlayerData>
rewards: Vec<Wrapper<PublicKey>>, // Vec<Wrapper<PublicKey>>
}
Generated Code
Rust
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Wrapper<T: BorshSerialize + BorshDeserialize> {
pub value: T,
}
#[derive(BorshSerialize, BorshDeserialize)]
pub enum Result<T: BorshSerialize + BorshDeserialize,
E: BorshSerialize + BorshDeserialize> {
Ok(T),
Err(E),
}
pub struct GameState {
pub player: Wrapper<PlayerData>,
pub rewards: Vec<Wrapper<Pubkey>>,
}TypeScript
export interface Wrapper<T> {
value: T;
}
export type Result<T, E> =
| { kind: 'Ok'; value: T }
| { kind: 'Err'; value: E };
export interface GameState {
player: Wrapper<PlayerData>;
rewards: Wrapper<PublicKey>[];
}
// Borsh schema (monomorphized)
export const WrapperPlayerDataBorshSchema = borsh.struct([
['value', PlayerDataBorshSchema],
]);
export const WrapperPublicKeyBorshSchema = borsh.struct([
['value', borsh.publicKey()],
]);Implementation
1. Parser Changes
Location: packages/core/src/parser.rs
pub struct TypeParameter {
pub name: Ident,
pub bounds: Vec<TraitBound>, // Future: trait bounds
}
pub struct StructDef {
pub name: Ident,
pub type_params: Vec<TypeParameter>, // NEW
pub fields: Vec<Field>,
}
impl StructDef {
pub fn parse_with_generics(input: &str) -> Result<Self, Error> {
// Parse: struct Name<T, U> { ... }
}
}2. Type Instantiation
Location: packages/core/src/transform.rs
struct TypeInstantiator {
type_params: HashMap<String, Type>,
}
impl TypeInstantiator {
fn instantiate(&self, ty: &Type) -> Type {
match ty {
Type::TypeParam(name) => {
self.type_params.get(name)
.cloned()
.unwrap_or(ty.clone())
}
Type::Generic { base, args } => {
// Instantiate generic type with concrete args
Type::Instantiated {
base: base.clone(),
args: args.iter().map(|a| self.instantiate(a)).collect(),
}
}
_ => ty.clone(),
}
}
}3. Monomorphization
For Borsh schemas, monomorphize generic types:
fn monomorphize_generic(
generic: &StructDef,
args: &[Type]
) -> StructDef {
let mut instantiated = generic.clone();
// Replace type parameters with concrete types
for (param, arg) in generic.type_params.iter().zip(args) {
instantiated = replace_type_param(instantiated, param, arg);
}
instantiated
}4. Rust Generator
Location: packages/core/src/generators/rust.rs
fn generate_struct_signature(struct_def: &StructDef) -> String {
let name = &struct_def.name;
if struct_def.type_params.is_empty() {
format\!("pub struct {}", name)
} else {
let params = struct_def.type_params.iter()
.map(|p| format\!("{}: BorshSerialize + BorshDeserialize", p.name))
.collect::<Vec<_>>()
.join(", ");
format\!("pub struct {}<{}>", name, params)
}
}5. TypeScript Generator
Location: packages/core/src/generators/typescript.rs
fn generate_generic_interface(struct_def: &StructDef) -> String {
let name = &struct_def.name;
if struct_def.type_params.is_empty() {
format\!("export interface {}", name)
} else {
let params = struct_def.type_params.iter()
.map(|p| p.name.as_str())
.collect::<Vec<_>>()
.join(", ");
format\!("export interface {}<{}>", name, params)
}
}
// Generate monomorphized Borsh schemas
fn generate_monomorphized_schemas(usage_sites: &[TypeUsage]) -> String {
// For each Wrapper<T> usage, generate WrapperTBorshSchema
}Examples
Example 1: Optional Wrapper
struct Optional<T> {
has_value: bool,
value: T,
}
struct Player {
nickname: Optional<String>,
}
Example 2: Pair Container
struct Pair<A, B> {
first: A,
second: B,
}
struct Trade {
offer: Pair<PublicKey, u64>, // (NFT, Price)
}
Example 3: Generic Enum
enum Status<T> {
Pending,
Active(T),
Completed(T),
}
struct Game {
state: Status<PublicKey>, // Player who's active
}
Constraints & Limitations
Borsh Constraint
All type parameters must implement Borsh:
struct Wrapper<T: BorshSerialize + BorshDeserialize> { ... }Monomorphization Required
TypeScript Borsh schemas are monomorphized (one per instantiation):
// Generic definition
interface Wrapper<T> { value: T }
// Monomorphized Borsh schemas
const WrapperPublicKeyBorshSchema = ...
const WrapperStringBorshSchema = ...No Higher-Kinded Types
Only simple generics (no F<_>):
struct Container<T> { ... } // ✓ Supported
struct Functor<F<_>> { ... } // ✗ Not supported
Testing
Unit Tests
#[test]
fn test_parse_generic_struct() {
let schema = parse_schema("struct Wrapper<T> { value: T }");
assert_eq\!(schema.types[0].type_params.len(), 1);
}
#[test]
fn test_instantiate_generic() {
let wrapper_def = /* Wrapper<T> */;
let instantiated = instantiate(&wrapper_def, &[Type::PublicKey]);
// Verify T replaced with PublicKey
}
#[test]
fn test_generate_generic_rust() {
let generic = /* ... */;
let rust = generate_struct(&generic);
assert\!(rust.contains("struct Wrapper<T: BorshSerialize>"));
}Integration Tests
- Parse generic structs and enums
- Instantiate with concrete types
- Generate Rust generics
- Generate TypeScript generics
- Monomorphize Borsh schemas
- Compile generated Rust code
Success Criteria
- Parser accepts generic type parameters
<T> - Supports multiple type params
<A, B, C> - Type parameter substitution works
- Generates correct Rust generics with bounds
- Generates correct TypeScript generics
- Monomorphizes Borsh schemas correctly
- Generic enums supported
- Nested generics work (
Vec<Wrapper<T>>) - All tests passing
- Documentation with examples
Documentation
Create New Files
-
docs/advanced/generics.md- Generics guide -
docs/advanced/monomorphization.md- Borsh schema generation
Update Files
-
docs/syntax.md- Document generic syntax -
README.md- Add generic example -
CHANGELOG.md- Document new feature -
ROADMAP.md- Mark Phase 5.3 item as complete ✅
Future Enhancements
- Trait bounds:
T: Clone + Debug - Where clauses:
where T: Sized - Associated types
- Const generics:
struct Array<T, const N: usize>
Related
- ROADMAP.md Phase 5.3 - Advanced Type System
- Complements: Add const generics support for fixed-size arrays in LUMOS #51 (const generics for arrays)
Priority: Medium
Complexity: Very High
Timeline: 7-10 days
📌 Remember: Update ROADMAP.md after completing this issue!
Metadata
Metadata
Assignees
Labels
area:coreCore compiler (parser, generator, IR, transform)Core compiler (parser, generator, IR, transform)type:enhancementImprovement to existing featureImprovement to existing featuretype:featureNew feature or functionalityNew feature or functionality