Skip to content

RFC 098 - Native associated types for traits #580

@dannymeijer

Description

@dannymeijer

Use this issue to propose an RFC topic and get early alignment.
If accepted, we’ll typically ask for a PR adding an RFC document under docs/RFCs/ based on the RFC template.

RFCs are user-facing only (language features, documentation, CLI/tooling, runtime surface area).
If your proposal is about Rust internals/compiler architecture, please open a bug/chore/feature issue instead.

Area

  • Incan Language (syntax/semantics)
  • Runtime / Core crates (stdlib/core/derive)
  • Documentation

Summary

RFC 098 proposes native associated types for Incan traits: trait-owned named type members that each implementation binds, with checked projection through Self.Item, H.Digest, or similar type-position syntax. The goal is to let Incan-authored traits express implementer-selected type relationships directly instead of multiplying helper traits, wrapper functions, or runtime dispatch paths.

Motivation

The current trait system can express method requirements, generic bounds, supertraits, and Rust trait adoption, but it cannot express a native Incan trait where the implementer chooses a type that other methods and generic helpers can recover. That gap showed up in std.hash, where a streaming hasher has shared update(...) behavior but different digest shapes, and also applies to iterators, parsers, codecs, resource readers, adapters, graph traversal, and Rust interop. RFC 023 and RFC 042 already identify associated types as future trait-system work; RFC 098 turns that into a source-level Incan feature rather than keeping it as a Rust-only interop detail.

Proposal sketch

Add associated type declarations inside native traits:

pub trait PullIterator:
    type Item

    def next(mut self) -> Option[Self.Item]: ...

Concrete adopters bind those members:

pub class Lines with PullIterator:
    type Item = str

    def next(mut self) -> Option[str]:
        ...

Generic code can project the implementer's chosen type through a bound:

def next_or_default[I with PullIterator](mut input: I, default: I.Item) -> I.Item:
    match input.next():
        Some(value) => return value
        None => return default

The RFC also defines missing-binding diagnostics, ambiguous projection rules, targeted bindings for same-name associated types, method signature compatibility, supertrait interactions, and the relationship to adjacent features such as generic associated types, associated constants, default associated types, specialization, trait objects, and equality constraints.

Draft RFC file: workspaces/docs-site/docs/RFCs/098_native_associated_types.md.

Alternatives considered

Keep using ordinary generic trait parameters for implementer-selected type families. That works when the caller chooses the type, but it forces APIs to carry generic arguments that are not real inputs to the capability.

Split traits by final value shape, such as byte-digest versus integer-digest hashers. That can work for tiny surfaces, but scales poorly and prevents one generic helper from returning the implementer's selected type.

Use union return types. That moves a static type relationship into runtime narrowing and makes callers branch even when the concrete implementation type is known.

Treat associated types as a Rust-only interop detail. That is insufficient because stdlib and user-authored Incan traits need the same modeling power without involving an external Rust trait.

Impact / compatibility

This is additive. Existing traits without associated types continue to work unchanged, and existing Rust trait associated type support from RFC 043 remains valid. The main impact is on the trait/typechecker model, generated backend signatures, formatter/LSP support, and stdlib APIs that can remove duplicated shape-specific abstractions once associated types exist.

Implementation notes (optional)

Likely layers: parser/AST for type Name in trait and adopter bodies, typechecker/symbol resolution for associated type metadata and projection, IR lowering/emission for preserving projected types, stdlib/runtime docs and APIs that dogfood the feature, formatter support, and LSP hover/completion/diagnostics.

Checklist

  • I checked for an existing RFC/issue covering this.
  • I can describe how this impacts existing code and how to migrate (if needed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCAdding or updating RFC documentsdocumentationImprovements or additions to documentationincan language semanticsSuggestions, features, or bugs related to the Incan Language itself (syntax and semantics)runtime / core cratesSuggestions, features, or bugs related to the `incan-core`, `incan-stdlib`, 'incan-derive` crates
    No fields configured for Feature.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions