Skip to content

tree-sitter: fix type<T>; parse failure in type position#2877

Merged
borisbat merged 1 commit into
masterfrom
bbatkin/ts-type-witness
May 26, 2026
Merged

tree-sitter: fix type<T>; parse failure in type position#2877
borisbat merged 1 commit into
masterfrom
bbatkin/ts-type-witness

Conversation

@borisbat
Copy link
Copy Markdown
Collaborator

Summary

Reported via Telegram (user Vi): Zed syntax highlighting breaks on type<…> used as a function parameter type, e.g.

def private get_type_id(t : type<auto(T)>) : int {
  print("{typeinfo typename(t)}")
  return -1
}

Root cause: the tree-sitter grammar only recognized type<T> in two places — inside _type_macro_arg (the inner sequence of a padded(type<T>, …) macro call) and as type_expression (which appears in expression positions only). Function parameters, return types, and struct fields declared with type<T> therefore fragmented the parse — even though this is the canonical witness-parameter form used throughout daslib (e.g. daslib/clargs.das lines 239/246/263/278/289).

Bison reference: type_declaration_no_options_no_dim → DAS_TYPE '<' type_declaration '>' (ds2_parser.ypp:3281).

Changes

  • New type_witness rule mirroring the bison production, added to _type so it's accepted wherever a type is expected (parameters, return types, struct fields, typedefs, generic args, etc.).
  • _type_macro_arg now reuses type_witness.
  • type_expression stays — it remains the expression-context form (let x = type<int>); the conflict declaration is updated to [type_expression, type_witness].
  • "type" @keyword in both queries/highlights.scm and zed-daslang/languages/daslang/highlights.scm already covers the keyword highlight globally; no query changes needed.

Tests

Five new corpus cases added to test/corpus/declarations.txt:

  1. Basic param — def parse_int(t : type<int>)
  2. Auto generic param — def get_type_id(t : type<auto(T)>) : int (the bug-report case)
  3. Return type — def make_witness() : type<int>
  4. Struct field — struct Foo { t : type<float> }
  5. Nested — def foo(t : type<array<int>>)

tree-sitter test result: 34/34 pass (5 new + 29 prior, no regressions).

Notes on parser.c regen

The 0.22.0 CLI pinned in package.json doesn't run on Node 24 (EISDIR on drive root during grammar.js module resolution), so generation used 0.26.9 (still ABI 14). The parser.c diff is large because of the CLI version bump on top of the rule addition; grammar.json (+52/-26) and node-types.json (+22/-2) reflect only the rule change.

Test plan

  • tree-sitter test (all 34 corpus cases pass)
  • tree-sitter parse on the bug-report snippet produces (type_witness type: (auto_type (identifier))) correctly nested under function_argument
  • tree-sitter parse on padded(type<int>, 16) in type position still produces (type_macro …) (existing path intact)
  • tree-sitter parse on let x = type<int> still produces (type_expression …) (expression path intact)

🤖 Generated with Claude Code

`type<T>` is a valid type in daslang (canonical witness-parameter form,
e.g. `t : type<auto(T)>` in clargs.das and elsewhere). The tree-sitter
grammar only recognized it inside `_type_macro_arg` (the inner sequence
of a `padded(type<T>, ...)` macro call) and as `type_expression` (which
appears in expression positions only). Function parameters, return
types, and struct fields declared with `type<T>` therefore fragmented
the parse -- breaking syntax highlighting in Zed and any other editor
using this grammar.

Add a dedicated `type_witness` rule mirroring bison's
`DAS_TYPE '<' type_declaration '>'` production (ds2_parser.ypp:3281)
and add it to `_type`. Reuse from `_type_macro_arg`. The existing
`type_expression` rule stays -- it remains the expression-context form
(e.g. `let x = type<int>`), and the conflict declaration is updated
to `[type_expression, type_witness]`.

Five new corpus tests cover: basic param, auto generic param (the bug
report case), return type, struct field, nested. All 34 corpus tests
pass; the previous 29 are unchanged.

parser.c regen also reflects a CLI version bump (the 0.22.0 cli no
longer runs on Node 24, so generation used 0.26.9 with ABI 14).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 26, 2026 00:21
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a tree-sitter parsing gap where type<...> (type-witness form) was only recognized in limited contexts, causing broken parses/highlighting when used in type positions like function parameters, return types, and struct fields.

Changes:

  • Introduces a dedicated type_witness rule and includes it in _type so type<T> is accepted anywhere a type is expected.
  • Reuses type_witness inside _type_macro_arg and updates the declared conflict to [type_expression, type_witness] to preserve expression-context type<...> parsing.
  • Adds new corpus coverage for type-witness usage in parameter, return type, struct field, and nested generic-type cases.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated no comments.

File Description
tree-sitter-daslang/grammar.js Adds type_witness, wires it into _type and _type_macro_arg, and updates the conflict set vs type_expression.
tree-sitter-daslang/src/grammar.json Regenerates the compiled grammar to include type_witness and the updated conflict declaration.
tree-sitter-daslang/src/node-types.json Regenerates node metadata to add the type_witness node and adjust affected parent/child relationships.
tree-sitter-daslang/test/corpus/declarations.txt Adds corpus cases verifying type<...> parses correctly in multiple type positions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@borisbat borisbat changed the title tree-sitter: fix type&lt;T&gt; parse failure in type position tree-sitter: fix type<T>; parse failure in type position May 26, 2026
@borisbat borisbat merged commit 2e848c9 into master May 26, 2026
30 checks passed
@borisbat borisbat deleted the bbatkin/ts-type-witness branch May 30, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants