10%

Section 15D: Bindings & Types

Goal: Implement binding syntax changes and type system simplifications

Source: docs/ori_lang/proposals/approved/


15D.1 Function-Level Contracts: pre() / post()

Proposal: proposals/approved/checks-proposal.md (semantics), proposals/approved/block-expression-syntax.md (syntax)

Function-level pre() and post() contract declarations for defensive programming. Contracts go between the return type and =:

@divide (a: int, b: int) -> int
    pre(b != 0)
    post(r -> r * b <= a)
= a div b

// Multiple conditions
@transfer (from: Account, to: Account, amount: int) -> (Account, Account)
    pre(amount > 0 | "amount must be positive")
    pre(from.balance >= amount | "insufficient funds")
    post((f, t) -> f.balance == from.balance - amount)
    post((f, t) -> t.balance == to.balance + amount)
= {
    // ... body ...
}

Key Design Decisions

  • Function-level placement: Contracts go on the declaration between return type and =
  • Multiple declarations: Use multiple pre() / post() declarations (not list syntax)
  • | for messages: Custom messages use condition | "message" syntax
  • Scope constraints: pre() can only access function parameters and module-level bindings; post() can access the result via lambda parameter
  • Void return: Compile error if post() used on a function returning void
  • Check modes deferred: check_mode: (enforce/observe/ignore) deferred to future proposal

Implementation

  • Implement: Parser: Parse pre() and post() on function declarations

    • Rust Tests: ori_parse/src/grammar/function.rs — contract parsing
    • Ori Tests: tests/spec/patterns/checks.ori
    • LLVM Support: LLVM codegen for contract parsing
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — contract parsing codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Parser: Support | "message" custom message syntax

    • Rust Tests: ori_parse/src/grammar/function.rs — message parsing
    • Ori Tests: tests/spec/patterns/check_messages.ori
    • LLVM Support: LLVM codegen for custom contract messages
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — custom contract messages codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Type checker: Validate pre() condition is bool

    • Rust Tests: ori_types/src/check/function.rs — pre type validation
    • Ori Tests: tests/compile-fail/checks/pre_not_bool.ori
    • LLVM Support: LLVM codegen for pre type validation
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — pre type validation codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Type checker: Validate post() is T -> bool lambda

    • Rust Tests: ori_types/src/check/function.rs — post type validation
    • Ori Tests: tests/compile-fail/checks/post_not_lambda.ori
    • LLVM Support: LLVM codegen for post type validation
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — post type validation codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Type checker: Error when post() used on void-returning function

    • Rust Tests: ori_types/src/check/function.rs — void return error
    • Ori Tests: tests/compile-fail/checks/post_void_return.ori
    • LLVM Support: LLVM codegen for void return error
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — void return error codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Scope checker: pre() can only access parameters and module-level bindings

    • Rust Tests: ori_types/src/check/scope.rs — pre scope validation
    • Ori Tests: tests/compile-fail/checks/pre_scope.ori
    • LLVM Support: LLVM codegen for pre scope validation
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — pre scope validation codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Codegen: Desugar to conditional checks and panics at function entry/exit

    • Rust Tests: ori_types/src/check/checks.rs — contract desugaring
    • Ori Tests: tests/spec/patterns/checks_desugaring.ori
    • LLVM Support: LLVM codegen for contract desugaring
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — contract desugaring codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Codegen: Embed source text for default error messages

    • Rust Tests: ori_types/src/check/checks.rs — source text embedding
    • Ori Tests: tests/spec/patterns/checks_error_messages.ori
    • LLVM Support: LLVM codegen for source text embedding
    • LLVM Rust Tests: ori_llvm/tests/syntax_tests.rs — source text embedding codegen
    • AOT Tests: No AOT coverage yet

15D.2 as Conversion Syntax

Proposal: proposals/approved/as-conversion-proposal.md

Replace int(), float(), str(), byte() with as/as? keyword syntax backed by As<T> and TryAs<T> traits.

// Before (special-cased positional args)
let x = int("42")
let y = float(value)

// After (consistent keyword syntax)
let x = "42" as? int
let y = value as float

Lexer

  • Implement: as keyword token (if not already reserved)
    • Rust Tests: ori_lexer/src/lib.rs — as keyword tokenization
    • Ori Tests: tests/spec/lexical/as_keyword.ori
    • LLVM Support: LLVM codegen for as keyword
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — as keyword codegen
    • AOT Tests: No AOT coverage yet

Parser

  • Implement: Parse expression as Type as conversion expression

    • Rust Tests: ori_parse/src/grammar/expr.rs — as expression parsing
    • Ori Tests: tests/spec/expressions/as_syntax.ori
    • LLVM Support: LLVM codegen for as expression
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — as expression codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Parse expression as? Type as fallible conversion

    • Rust Tests: ori_parse/src/grammar/expr.rs — as? expression parsing
    • Ori Tests: tests/spec/expressions/as_fallible_syntax.ori
    • LLVM Support: LLVM codegen for as? expression
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — as? expression codegen
    • AOT Tests: No AOT coverage yet

Type Checker

  • Implement: Validate as only used with As<T> trait implementations

    • Rust Tests: ori_types/src/check/as_expr.rs
    • Ori Tests: tests/compile-fail/as_not_implemented.ori
    • LLVM Support: LLVM codegen for As trait validation
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — As trait validation codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Validate as? only used with TryAs<T> trait implementations

    • Rust Tests: ori_types/src/check/as_expr.rs
    • Ori Tests: tests/compile-fail/try_as_not_implemented.ori
    • LLVM Support: LLVM codegen for TryAs trait validation
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — TryAs trait validation codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Error when using as for fallible conversion (must use as?)

    • Rust Tests: ori_types/src/check/as_expr.rs
    • Ori Tests: tests/compile-fail/as_fallible_conversion.ori
    • LLVM Support: LLVM codegen for fallible conversion error
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — fallible conversion error codegen
    • AOT Tests: No AOT coverage yet

Codegen

  • Implement: Desugar x as T to As<T>.as(self: x)
    • LLVM Support: LLVM codegen for as desugaring
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — as desugaring codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Desugar x as? T to TryAs<T>.try_as(self: x)
    • LLVM Support: LLVM codegen for as? desugaring
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — as? desugaring codegen
    • AOT Tests: No AOT coverage yet

Migration

  • Implement: Remove int(), float(), str(), byte() from parser
    • LLVM Support: LLVM codegen for type conversion removal
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — type conversion removal codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Update error messages to suggest as syntax
    • LLVM Support: LLVM codegen for as syntax suggestion
    • LLVM Rust Tests: ori_llvm/tests/as_conversion_tests.rs — as syntax suggestion codegen
    • AOT Tests: No AOT coverage yet

15D.3 Simplified Bindings with $ for Immutability

Proposal: proposals/approved/simplified-bindings-proposal.md

Simplify the binding model: let x is mutable, let $x is immutable. Remove mut keyword. Module-level bindings require $ prefix.

// Before
let x = 5         // immutable
let mut x = 5     // mutable
$timeout = 30s    // config variable

// After
let x = 5         // mutable
let $x = 5        // immutable
let $timeout = 30s // module-level constant (let and $ required)

Lexer

  • Implement: Remove mut from reserved keywords
    • Rust Tests: ori_lexer/src/lib.rs — keyword list update
    • Ori Tests: tests/spec/lexical/mut_not_keyword.ori
    • LLVM Support: LLVM codegen for mut removal
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — mut removal codegen
    • AOT Tests: No AOT coverage yet

Parser

  • Implement: Update let_expr to accept $ prefix in binding pattern (2026-02-20)

    • Rust Tests: ori_parse/src/tests/parser.rs — block let binding with $ prefix
    • Ori Tests: tests/spec/expressions/immutable_bindings.ori
    • LLVM Support: LLVM codegen for immutable binding parsing
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — immutable binding parsing codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Remove mut from let_expr grammar

    • Rust Tests: ori_parse/src/grammar/expr.rs — mut removal
    • Ori Tests: All 151 let mut occurrences migrated to let across 25 test files + AOT tests
    • LLVM Support: LLVM codegen for mut removal
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — mut removal codegen
    • AOT Tests: ori_llvm/tests/aot/mutations.rs — all 21 tests use let x (mutable-by-default) with reassignment, confirming mut removal works end-to-end in AOT
  • Implement: Update constant_decl to require let $name = expr

    • Rust Tests: ori_parse/src/grammar/decl.rs — constant declaration parsing
    • Ori Tests: tests/spec/declarations/constants.ori
    • LLVM Support: LLVM codegen for constant declaration
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — constant declaration codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Remove old const function syntax $name (params) -> Type

    • Rust Tests: ori_parse/src/grammar/decl.rs — const function removal
    • Ori Tests: tests/compile-fail/old_const_function_syntax.ori
    • LLVM Support: LLVM codegen for const function removal
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — const function removal codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Support $ prefix in destructuring patterns (2026-02-20)

    • Rust Tests: ori_parse/src/grammar/expr/primary.rsparse_binding_pattern handles $ for Name, Tuple, Struct, List
    • Ori Tests: tests/spec/expressions/immutable_bindings.ori — tuple, struct, list destructuring with $
    • LLVM Support: LLVM codegen for destructure immutable
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — destructure immutable codegen
    • AOT Tests: No AOT coverage yet
  • Fix: List rest binding ..rest tracks $ mutability (2026-02-20)

    • IR: BindingPattern::List.rest changed from Option<Name> to Option<(Name, bool)> (ori_ir/src/ast/patterns/binding.rs:31)
    • IR: CanBindingPattern::List.rest changed to Option<(Name, bool)> (ori_ir/src/canon/patterns.rs:32)
    • Parser: parse_binding_pattern handles $ before rest identifier (ori_parse/src/grammar/expr/primary.rs:1386)
    • Type checker: bind_pattern() uses bind_with_mutability() for rest (ori_types/src/infer/expr/sequences.rs:489)
    • Evaluator: bind_can_pattern() uses per-binding rest_mutable (ori_eval/src/interpreter/can_eval.rs:758)
    • Canon: lowering passes through (Name, bool) tuple (ori_canon/src/lower/patterns.rs:261)
    • Formatter: emits $ prefix on immutable rest bindings (ori_fmt/src/formatter/patterns.rs:183)
    • Grammar: grammar.ebnf updated to allow [ "$" ] on rest identifier (line 581)

Semantic Analysis

  • Implement: Track $ modifier separately from identifier name (2026-02-20)

    • Rust Tests: ori_types/src/infer/env/mod.rsTypeEnvInner::mutability FxHashMap tracks per-binding mutability
    • Ori Tests: tests/spec/expressions/mutable_vs_immutable.ori — verifies $ bindings preserve immutability
    • LLVM Support: N/A — mutability is a type-checker concern, not codegen
    • LLVM Rust Tests: N/A — mutability is a type-checker concern, not codegen
  • Implement: Prevent $x and x coexisting in same scope

    • Rust Tests: ori_types/src/check/binding.rs — same-name conflict detection
    • Ori Tests: tests/compile-fail/dollar_and_non_dollar_conflict.ori
    • LLVM Support: LLVM codegen for same-name conflict detection
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — same-name conflict detection codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Enforce module-level bindings require $ prefix

    • Rust Tests: ori_types/src/check/module.rs — module binding immutability
    • Ori Tests: tests/compile-fail/module_level_mutable.ori
    • LLVM Support: LLVM codegen for module binding immutability
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — module binding immutability codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Enforce $-prefixed bindings cannot be reassigned (2026-02-20)

    • Rust Tests: ori_types/src/infer/expr/operators.rs — immutability check in infer_assign
    • Ori Tests: tests/compile-fail/assign_to_immutable.ori, assign_to_immutable_in_loop.ori, assign_to_immutable_destructured.ori
    • LLVM Support: N/A — compile-time type error (E2039) prevents codegen
    • LLVM Rust Tests: N/A — compile-time type error prevents codegen

Imports

  • Implement: Require $ in import statements for immutable bindings

    • Rust Tests: ori_types/src/check/import.rs — import with dollar
    • Ori Tests: tests/spec/modules/import_immutable.ori
    • LLVM Support: LLVM codegen for import with dollar
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — import with dollar codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Error when importing $x as x or vice versa

    • Rust Tests: ori_types/src/check/import.rs — import modifier mismatch
    • Ori Tests: tests/compile-fail/import_dollar_mismatch.ori
    • LLVM Support: LLVM codegen for import modifier mismatch
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — import modifier mismatch codegen
    • AOT Tests: No AOT coverage yet

Shadowing

  • Implement: Allow shadowing to change mutability
    • Rust Tests: ori_types/src/check/binding.rs — shadowing mutability change
    • Ori Tests: tests/spec/expressions/shadow_mutability.ori
    • LLVM Support: LLVM codegen for shadowing mutability change
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — shadowing mutability change codegen
    • AOT Tests: No AOT coverage yet

Error Messages

  • Implement: Clear error for reassignment to immutable binding (2026-02-20)

    • Rust Tests: ori_types/src/type_error/check_error/mod.rsAssignToImmutable variant + formatting
    • Ori Tests: tests/compile-fail/assign_to_immutable.ori (verifies “cannot assign to immutable binding” message)
    • LLVM Support: N/A — compile-time type error prevents codegen
    • LLVM Rust Tests: N/A — compile-time type error prevents codegen
  • Implement: Clear error for module-level mutable binding

    • Rust Tests: ori_diagnostic/src/problem.rs — module mutable error
    • Ori Tests: tests/compile-fail/module_mutable_message.ori
    • LLVM Support: LLVM codegen for module mutable error
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — module mutable error codegen
    • AOT Tests: No AOT coverage yet
  • Implement: Migration hint for old let mut syntax

    • Rust Tests: ori_diagnostic/src/problem.rs — let mut migration hint
    • Ori Tests: tests/compile-fail/let_mut_migration.ori
    • LLVM Support: LLVM codegen for let mut migration hint
    • LLVM Rust Tests: ori_llvm/tests/binding_tests.rs — let mut migration hint codegen
    • AOT Tests: No AOT coverage yet

15D.4 Remove dyn Keyword for Trait Objects

Proposal: proposals/approved/remove-dyn-keyword-proposal.md

Remove the dyn keyword for trait objects. Trait names used directly as types mean “any value implementing this trait.”

// Before
@process (item: dyn Printable) -> void = ...
let items: [dyn Serializable] = ...

// After
@process (item: Printable) -> void = ...
let items: [Serializable] = ...

Implementation

  • Implement: Remove "dyn" type from grammar type production

    • Rust Tests: ori_parse/src/grammar/ty.rs — dyn removal tests
    • Ori Tests: tests/spec/types/trait_objects.ori
    • LLVM Support: LLVM codegen for trait objects without dyn
    • LLVM Rust Tests: ori_llvm/tests/trait_object_tests.rs
    • AOT Tests: No AOT coverage yet
  • Implement: Parser recognizes trait name in type position as trait object

    • Rust Tests: ori_parse/src/grammar/ty.rs — trait-as-type parsing
    • Ori Tests: tests/spec/types/trait_objects.ori
    • LLVM Support: LLVM codegen for trait-as-type
    • LLVM Rust Tests: ori_llvm/tests/trait_object_tests.rs
    • AOT Tests: No AOT coverage yet
  • Implement: Type checker distinguishes item: Trait (trait object) vs <T: Trait> (generic bound)

    • Rust Tests: ori_types/src/check/trait_objects.rs
    • Ori Tests: tests/spec/types/trait_vs_bound.ori
    • LLVM Support: LLVM codegen for trait object vs bound distinction
    • LLVM Rust Tests: ori_llvm/tests/trait_object_tests.rs
    • AOT Tests: No AOT coverage yet
  • Implement: Object safety validation with clear error messages

    • Rust Tests: ori_types/src/check/object_safety.rs
    • Ori Tests: tests/compile-fail/non_object_safe_trait.ori
    • LLVM Support: LLVM codegen for object safety validation
    • LLVM Rust Tests: ori_llvm/tests/trait_object_tests.rs
    • AOT Tests: No AOT coverage yet
  • Implement: Error if dyn keyword is used (helpful migration message)

    • Rust Tests: ori_parse/src/grammar/ty.rs — dyn keyword error
    • Ori Tests: tests/compile-fail/dyn_keyword_removed.ori

15D.5 Index and Field Assignment

Proposal: proposals/approved/index-assignment-proposal.md

Extend assignment targets to support index expressions (list[i] = x), field access (state.name = x), mixed chains (state.items[i] = x, list[i].name = x), and compound assignment on all forms (list[i] += 1). All forms desugar to copy-on-write reassignment via IndexSet trait (for index) or struct spread (for fields).

let list = [1, 2, 3]
list[0] = 10                          // list = list.updated(key: 0, value: 10)

let state = GameState { score: 0, level: 1 }
state.score = 100                     // state = { ...state, score: 100 }
state.items[i] = new_item             // mixed chain
list[i].name = "new"                  // index then field

list[0] += 5                          // compound: list[0] = list[0] + 5

Phase 1: IndexSet Trait and updated Method

  • Implement: Define IndexSet<Key, Value> trait in prelude — @updated (self, key: Key, value: Value) -> Self

    • Rust Tests: ori_types/src/infer/ — IndexSet trait resolution
    • Ori Tests: tests/spec/traits/index_set/basic.ori
  • Implement: Register updated as built-in method on [T], {K: V}, [T, max N] in evaluator

    • Rust Tests: ori_eval/src/method_dispatch/ — updated method dispatch
    • Ori Tests: tests/spec/traits/index_set/updated_method.ori
  • Implement: updated with ARC-aware copy-on-write in ori_patterns/ori_eval

    • Rust Tests: ori_patterns/src/value/ — copy-on-write behavior
    • Ori Tests: tests/spec/traits/index_set/cow_behavior.ori

Phase 2: Parser Changes

  • Implement: Extend parser to accept assignment_target (identifier + index/field chains) on LHS of = and compound operators

    • Rust Tests: ori_parse/src/grammar/expr/ — assignment target parsing
    • Ori Tests: tests/spec/expressions/index_assignment_syntax.ori
  • Implement: Emit AST node capturing chain of index/field accesses in assignment target

    • Rust Tests: ori_ir/src/ast/expr.rs — AssignTarget AST node
    • Ori Tests: tests/spec/expressions/field_assignment_syntax.ori

Phase 3: Type-Directed Desugaring

  • Implement: Desugar [key] steps to updated() calls (requires IndexSet trait resolution)

    • Rust Tests: ori_types/src/infer/expr/ — index assignment desugaring
    • Ori Tests: tests/spec/expressions/index_assignment_desugar.ori
  • Implement: Desugar .field steps to struct spread reconstruction (requires struct type info)

    • Rust Tests: ori_types/src/infer/expr/ — field assignment desugaring
    • Ori Tests: tests/spec/expressions/field_assignment_desugar.ori
  • Implement: Handle nested cases, mixed field-index chains, and compound assignment

    • Rust Tests: ori_types/src/infer/expr/ — mixed chain desugaring
    • Ori Tests: tests/spec/expressions/mixed_chain_assignment.ori

Phase 4: Type Checker Integration

  • Implement: Validate mutability of root binding (not $, not parameter, not loop variable)

    • Rust Tests: ori_types/src/infer/expr/ — mutability validation
    • Ori Tests: tests/spec/expressions/assignment_mutability.ori
  • Implement: Validate field names against struct types in assignment chains

    • Rust Tests: ori_types/src/infer/expr/ — field validation
    • Ori Tests: tests/compile-fail/assignment/invalid_field.ori
  • Implement: Validate key and value types against IndexSet impl

    • Rust Tests: ori_types/src/infer/expr/ — IndexSet type validation
    • Ori Tests: tests/compile-fail/assignment/type_mismatch.ori
  • Implement: Emit diagnostics for all error cases (immutable binding, parameter, loop var, missing IndexSet, field mismatch, type mismatch)

    • Rust Tests: ori_diagnostic/ — assignment error diagnostics
    • Ori Tests: tests/compile-fail/assignment/all_errors.ori

Phase 5: LLVM Support

  • LLVM Support: LLVM codegen for index assignment desugaring
    • LLVM Rust Tests: ori_llvm/tests/ — index assignment codegen
    • AOT Tests: No AOT coverage yet
  • LLVM Support: LLVM codegen for field assignment desugaring
    • LLVM Rust Tests: ori_llvm/tests/ — field assignment codegen
    • AOT Tests: No AOT coverage yet
  • LLVM Support: LLVM codegen for compound assignment on extended targets
    • LLVM Rust Tests: ori_llvm/tests/ — compound assignment codegen
    • AOT Tests: No AOT coverage yet

15D.6 Mutable Self

Proposal: proposals/approved/mutable-self-proposal.md

Make self a mutable binding in method bodies with implicit mutation propagation back to the caller. Extends the existing field/index assignment desugaring pattern to method calls.

impl Cursor {
    @advance (self) -> void = {
        self.pos += 1
    }
}

cursor.advance()   // cursor is updated via desugaring

Phase 1: Self Mutability

  • Implement: Make self a mutable binding in method bodies (type checker)

    • Rust Tests: ori_types/src/infer/ — self mutability in methods
    • Ori Tests: tests/spec/methods/mutable_self_basic.ori
  • Implement: Mutation detection dataflow analysis (classify methods as mutating/non-mutating)

    • Rust Tests: ori_types/src/infer/ — mutation classification
    • Ori Tests: tests/spec/methods/mutation_detection.ori

Phase 2: Call-Site Desugaring

  • Implement: Void-returning mutating methods desugar to -> Self + implicit reassignment

    • Rust Tests: ori_types/src/infer/expr/ — void method desugaring
    • Ori Tests: tests/spec/methods/mutable_self_void.ori
  • Implement: Value-returning mutating methods desugar to -> (Self, T) + tuple split

    • Rust Tests: ori_types/src/infer/expr/ — value method desugaring
    • Ori Tests: tests/spec/methods/mutable_self_value_return.ori
  • Implement: No desugaring for -> Self methods (already return Self)

    • Rust Tests: ori_types/src/infer/expr/ — Self return carve-out
    • Ori Tests: tests/spec/methods/mutable_self_returns_self.ori
  • Implement: Nested field mutation cascading (self.inner.advance())

    • Rust Tests: ori_types/src/infer/expr/ — nested mutation desugaring
    • Ori Tests: tests/spec/methods/mutable_self_nested.ori

Phase 3: Caller Validation

  • Implement: Error when calling mutating method on immutable ($) binding

    • Rust Tests: ori_types/src/infer/expr/ — immutable receiver error
    • Ori Tests: tests/compile-fail/methods/mutating_on_immutable.ori
  • Implement: Diagnostics for mutation-related errors

    • Rust Tests: ori_diagnostic/ — mutation error diagnostics
    • Ori Tests: tests/compile-fail/methods/mutation_errors.ori

Phase 4: Trait Integration

  • Implement: Infer mutation classification across trait implementations

    • Rust Tests: ori_types/src/infer/ — trait mutation consistency
    • Ori Tests: tests/spec/traits/mutable_self_trait.ori
  • Implement: Conservative mutating classification for trait objects without local impls

    • Rust Tests: ori_types/src/infer/ — trait object mutation
    • Ori Tests: tests/spec/traits/mutable_self_trait_object.ori

Phase 5: Extension Support

  • Implement: Extension methods follow same mutation propagation rules
    • Rust Tests: ori_types/src/infer/ — extension mutation propagation
    • Ori Tests: tests/spec/methods/mutable_self_extension.ori

Phase 6: Evaluator

  • Implement: Evaluator support for mutable self in method bodies

    • Rust Tests: ori_eval/src/ — mutable self evaluation
    • Ori Tests: tests/spec/methods/mutable_self_eval.ori
  • Implement: Evaluator call-site desugaring (implicit reassignment)

    • Rust Tests: ori_eval/src/ — call-site desugaring evaluation
    • Ori Tests: tests/spec/methods/mutable_self_propagation.ori

Phase 7: LLVM Support

  • LLVM Support: LLVM codegen for mutable self desugaring

    • LLVM Rust Tests: ori_llvm/tests/ — mutable self codegen
    • AOT Tests: tests/spec/methods/mutable_self_aot.ori
  • LLVM Support: COW integration for self-mutating methods

    • LLVM Rust Tests: ori_llvm/tests/ — mutable self COW codegen
    • AOT Tests: tests/spec/methods/mutable_self_cow.ori

15D.7 Section Completion Checklist

  • All implementation items have checkboxes marked [ ]
  • All spec docs updated
  • CLAUDE.md updated with syntax changes
  • Migration tools working
  • All tests pass: ./test-all.sh

Exit Criteria: Binding and type syntax proposals implemented