100%

Goal

Add the inferred-return typed lambda form to ori_parse, with =-delimiter disambiguation via the shared try_parse_lambda_return_type() helper. Parser-only; reuses the existing ExprKind::Lambda lowering. The bare -> Type shape is parse-ambiguous with (x: int) -> x and resolves to E2005 at typeck (proposal Errata 2026-05-31), not a parse diagnostic.

Intelligence Reconnaissance

Queries (2026-05-31): scripts/intel-query.sh symbols "lambda" --repo ori; scripts/intel-query.sh similar parse_typed_lambda_body --repo rust,swift,go.

  • [ori:compiler/ori_arc/src/lower/calls/lambda.rs] lower_lambda — the new form reuses this lowering (same ExprKind::Lambda node); no ARC change.
  • [ori:compiler/ori_eval/src/interpreter/can_eval/function_exp.rs] eval_can_lambda — evaluator reuse confirmed; no eval change.
  • [ori] No symbol collision: (x: T) -> body is a parser front-end change feeding the existing lambda pipeline.
  • Prior art (graph): typescript#40750, swift#11478, roc#9145 concern lambda-return-inference quality, not existence — Rust/Swift/Gleam/TS all infer it.

Implementation Sketch

ori_parse/src/grammar/expr/primary/collections.rs currently routes a parenthesized expression into parse_typed_lambda_body the moment a parameter is typed, then unconditionally requires -> type = body (E1005 when no return type, E1017 when no =). Replace that with the unified lambda_tail rule: after ->, speculatively parse a type; if = follows, it is the explicit-return form; otherwise restore the snapshot and parse the tail as a body expression, building ExprKind::Lambda { params, ret_ty: ParsedTypeId::INVALID, body }. The shared try_parse_lambda_return_type() helper already implements this; parse_typed_lambda_body reuses it (DRY). The bare -> Type case is parse-ambiguous with (x: int) -> x and resolves to a type-name-as-value E2005 at typeck (proposal Errata 2026-05-31), not a parse diagnostic.

Implementation Items

  • Write the parser test matrix — positive pins (inferred, operator-body, multi-param) + negative pins (juxtaposition, mixed-param E1018) added in tests/parser.rs; the conformance corpus is the integration gate.
  • In collections.rs, route parse_typed_lambda_body through the SSOT try_parse_lambda_return_type() helper (snapshot → parse_type()=-delimiter), the same disambiguation the ()-lambda path uses. DRY — no parallel logic.
  • Explicit-return branch: type = consumed, ret_ty = the annotated type (via the shared helper).
  • Inferred-return branch: no =ret_ty: ParsedTypeId::INVALID, body parsed as an expression.
  • Bare--> Type edge case — REFINED (per proposal Errata 2026-05-31): parse-ambiguous with the valid (x: int) -> x form, so no parse diagnostic; (x: int) -> int parses as body int and the type-name-as-value fails type inference (E2005). Clause 14 updated to match.
  • Clear the ori_parse clippy regression (task #5 — landed 5bdb49e19).
  • Verify debug + dual-execution parity; cargo test -p ori_parse --lib (470 pass), interpreter + LLVM both green on lambdas.ori (30 each).

Spec References

  • Proposal: compiler_repo/docs/ori_lang/proposals/approved/typed-lambda-inferred-return-proposal.md §Design / §Disambiguation.
  • Grammar: grammar.ebnf:550-553 (lambda / simple_lambda / typed_lambda).
  • Spec clause: 14-expressions.md:149.
  • Parser rules: parse.md §SN-3 (speculative parse / snapshot), §PR-6 (lambda layering).

Tests

Matrix dimensions (rows = lambda shape; columns = expected parse outcome):

ShapeExpected
(x: int) -> x * 2Lambda{ret_ty: INVALID}, body x * 2
(x: int) -> int = xLambda{ret_ty: int}, body x
(x: int) -> Foo == yLambda{ret_ty: INVALID}, body Foo == y
(a: int, b: int) -> a - bLambda{ret_ty: INVALID}, two typed params
(x: int) -> int (no body)parses as body int; type-name-as-value → E2005 at typeck
(x) -> xuntyped simple_lambda (unchanged)
(x: int, y) -> ...E1018 (mixed typed/untyped, unchanged)
  • Positive pins: typed-param inferred-return parses to ret_ty: INVALID; explicit-return parses to the annotated type.
  • Negative pins: juxtaposed (x: int) -> int x is still rejected (trailing token, no longer E1017); mixed params still emit E1018.
  • Rust unit tests in ori_parse (token-stream / AST-shape assertions); the .ori conformance corpus is the section-11 gate.