feat: implement type classes / traits

Add support for type classes (traits) with full parsing, type checking, and
validation. The implementation includes:

- Trait declarations: trait Show { fn show(x: T): String }
- Trait implementations: impl Show for Int { fn show(x: Int) = ... }
- Super traits: trait Ord: Eq { ... }
- Trait constraints in where clauses: where T: Show + Eq
- Type parameters on traits: trait Functor<F> { ... }
- Default method implementations
- Validation of required method implementations

This provides a foundation for ad-hoc polymorphism and enables
more expressive type-safe abstractions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 04:51:06 -05:00
parent df5c0a1a32
commit 05a85ea27f
8 changed files with 675 additions and 10 deletions

View File

@@ -215,7 +215,9 @@ impl Parser {
TokenKind::Handler => Ok(Declaration::Handler(self.parse_handler_decl()?)),
TokenKind::Type => Ok(Declaration::Type(self.parse_type_decl(visibility)?)),
TokenKind::Let => Ok(Declaration::Let(self.parse_let_decl(visibility)?)),
_ => Err(self.error("Expected declaration (fn, effect, handler, type, or let)")),
TokenKind::Trait => Ok(Declaration::Trait(self.parse_trait_decl(visibility)?)),
TokenKind::Impl => Ok(Declaration::Impl(self.parse_impl_decl()?)),
_ => Err(self.error("Expected declaration (fn, effect, handler, type, trait, impl, or let)")),
}
}
@@ -503,6 +505,267 @@ impl Parser {
})
}
/// Parse trait declaration: trait Show { fn show(self): String }
fn parse_trait_decl(&mut self, visibility: Visibility) -> Result<TraitDecl, ParseError> {
let start = self.current_span();
self.expect(TokenKind::Trait)?;
let name = self.parse_ident()?;
// Optional type parameters: trait Functor<F> { ... }
let type_params = if self.check(TokenKind::Lt) {
self.parse_type_params()?
} else {
Vec::new()
};
// Optional super traits: trait Ord: Eq { ... }
let super_traits = if self.check(TokenKind::Colon) {
self.advance();
self.parse_trait_bounds()?
} else {
Vec::new()
};
self.expect(TokenKind::LBrace)?;
self.skip_newlines();
let mut methods = Vec::new();
while !self.check(TokenKind::RBrace) {
methods.push(self.parse_trait_method()?);
self.skip_newlines();
if self.check(TokenKind::Comma) {
self.advance();
}
self.skip_newlines();
}
let end = self.current_span();
self.expect(TokenKind::RBrace)?;
Ok(TraitDecl {
visibility,
name,
type_params,
super_traits,
methods,
span: start.merge(end),
})
}
/// Parse a trait method signature
fn parse_trait_method(&mut self) -> Result<TraitMethod, ParseError> {
let start = self.current_span();
self.expect(TokenKind::Fn)?;
let name = self.parse_ident()?;
// Optional type parameters
let type_params = if self.check(TokenKind::Lt) {
self.parse_type_params()?
} else {
Vec::new()
};
self.expect(TokenKind::LParen)?;
let params = self.parse_params()?;
self.expect(TokenKind::RParen)?;
self.expect(TokenKind::Colon)?;
let return_type = self.parse_type()?;
// Optional default implementation
let default_impl = if self.check(TokenKind::Eq) {
self.advance();
self.skip_newlines();
Some(self.parse_expr()?)
} else {
None
};
let span = start.merge(self.previous_span());
Ok(TraitMethod {
name,
type_params,
params,
return_type,
default_impl,
span,
})
}
/// Parse trait bounds: Eq + Ord + Show
fn parse_trait_bounds(&mut self) -> Result<Vec<TraitBound>, ParseError> {
let mut bounds = Vec::new();
loop {
bounds.push(self.parse_trait_bound()?);
if self.check(TokenKind::Plus) {
self.advance();
} else {
break;
}
}
Ok(bounds)
}
/// Parse a single trait bound: Show, Functor<F>
fn parse_trait_bound(&mut self) -> Result<TraitBound, ParseError> {
let start = self.current_span();
let trait_name = self.parse_ident()?;
let type_args = if self.check(TokenKind::Lt) {
self.advance();
let mut args = Vec::new();
while !self.check(TokenKind::Gt) {
args.push(self.parse_type()?);
if !self.check(TokenKind::Gt) {
self.expect(TokenKind::Comma)?;
}
}
self.expect(TokenKind::Gt)?;
args
} else {
Vec::new()
};
let span = start.merge(self.previous_span());
Ok(TraitBound {
trait_name,
type_args,
span,
})
}
/// Parse impl declaration: impl Show for Int { ... }
fn parse_impl_decl(&mut self) -> Result<ImplDecl, ParseError> {
let start = self.current_span();
self.expect(TokenKind::Impl)?;
// Optional type parameters: impl<T> Show for List<T> { ... }
let type_params = if self.check(TokenKind::Lt) {
self.parse_type_params()?
} else {
Vec::new()
};
// Parse the trait name
let trait_name = self.parse_ident()?;
// Optional type arguments for the trait: impl Functor<List> for ...
let trait_args = if self.check(TokenKind::Lt) {
self.advance();
let mut args = Vec::new();
while !self.check(TokenKind::Gt) {
args.push(self.parse_type()?);
if !self.check(TokenKind::Gt) {
self.expect(TokenKind::Comma)?;
}
}
self.expect(TokenKind::Gt)?;
args
} else {
Vec::new()
};
self.expect(TokenKind::For)?;
let target_type = self.parse_type()?;
// Optional where clause with trait constraints
let constraints = if self.check(TokenKind::Where) {
self.parse_trait_constraints()?
} else {
Vec::new()
};
self.expect(TokenKind::LBrace)?;
self.skip_newlines();
let mut methods = Vec::new();
while !self.check(TokenKind::RBrace) {
methods.push(self.parse_impl_method()?);
self.skip_newlines();
if self.check(TokenKind::Comma) {
self.advance();
}
self.skip_newlines();
}
let end = self.current_span();
self.expect(TokenKind::RBrace)?;
Ok(ImplDecl {
type_params,
constraints,
trait_name,
trait_args,
target_type,
methods,
span: start.merge(end),
})
}
/// Parse trait constraints in a where clause: where T: Show, U: Eq + Ord
fn parse_trait_constraints(&mut self) -> Result<Vec<TraitConstraint>, ParseError> {
let mut constraints = Vec::new();
while self.check(TokenKind::Where) {
self.advance();
let start = self.current_span();
let type_param = self.parse_ident()?;
self.expect(TokenKind::Colon)?;
let bounds = self.parse_trait_bounds()?;
let span = start.merge(self.previous_span());
constraints.push(TraitConstraint {
type_param,
bounds,
span,
});
if self.check(TokenKind::Comma) {
self.advance();
}
}
Ok(constraints)
}
/// Parse an impl method
fn parse_impl_method(&mut self) -> Result<ImplMethod, ParseError> {
let start = self.current_span();
self.expect(TokenKind::Fn)?;
let name = self.parse_ident()?;
self.expect(TokenKind::LParen)?;
let params = self.parse_params()?;
self.expect(TokenKind::RParen)?;
// Optional return type (infer if not provided)
let return_type = if self.check(TokenKind::Colon) {
self.advance();
Some(self.parse_type()?)
} else {
None
};
self.expect(TokenKind::Eq)?;
self.skip_newlines();
let body = self.parse_expr()?;
let span = start.merge(body.span());
Ok(ImplMethod {
name,
params,
return_type,
body,
span,
})
}
/// Parse type parameters <A, B, C>
fn parse_type_params(&mut self) -> Result<Vec<Ident>, ParseError> {
self.expect(TokenKind::Lt)?;