feat: parenthesized type grouping — (T) groups, (T,) is a 1-tuple (issue 0177)

In type position, parentheses now mirror value position: (T) (a single
unnamed element, no trailing comma) is a GROUPING that resolves to the
inner type; (T,) is a 1-tuple; (A, B) a 2-tuple; named (x: T) and spread
(..Ts) stay tuples; (...) -> R stays a function type. This lets a
closure/optional/function type be parenthesized for readability without
silently becoming a 1-tuple:
  [1](Closure(i64,i64) -> i64)   // array of closures (issue 0177) -> 7
  ?(?i64)                        // genuine nested optional (issue 0165 intent)

Parser: src/parser.zig returns the inner node for a single unnamed
non-spread no-trailing-comma parenthesized type. formatTypeName (both
generic.zig diagnostics + types.zig reflection) now render a 1-tuple as
(T,) so the spelling is unambiguous and diagnostics are self-consistent.
The 0165 coerce/stmt note reworded accordingly.

specs.md §Type Syntax updated; basic/0036 wrap return -> (i64,); obsolete
diagnostic 1195 removed (?(?i64) now compiles); regression
examples/types/0201-types-parenthesized-type-grouping.sx added; 0414 .ir
golden regenerated for the (T,) rendering. Resolves 0177; updates
0165/0170. Verified by 3 adversarial reviews; suite 792/0.
This commit is contained in:
agra
2026-06-23 10:43:47 +03:00
parent c41f51aed3
commit 555ccdc024
18 changed files with 120 additions and 40 deletions

View File

@@ -1,5 +1,19 @@
# 0177 — calling a closure stored in an array element directly (`fns[i](args)`) crashes / miscompiles
> **RESOLVED via parenthesized-type grouping.** The repro
> `[1](Closure(i64,i64) -> i64) = .[ add ]` was not an array of closures — under
> the old rule `(Closure(...) -> R)` was a 1-tuple, so it was an array of
> 1-tuples and `fns[0](...)` tried to call a tuple → LLVM "Called function must
> be a pointer!". Per the user's direction, parentheses in TYPE position are now
> a GROUPING (mirroring value position): `(T)` (no trailing comma) resolves to
> the inner type, `(T,)` is the 1-tuple. So `[1](Closure(...) -> R)` is now an
> array of closures and `fns[0](3,4)` returns `7`. (The canonical non-paren
> `[1]Closure(...) -> R = .[ add ]` already worked.) Implemented in
> `src/parser.zig` (single unnamed non-spread element, no trailing comma →
> return the inner type node). Regression:
> `examples/types/0201-types-parenthesized-type-grouping.sx`. specs.md §Type
> Syntax updated. Verified by 3 adversarial reviews; suite 792/0.
## Symptom
A closure (or `Closure(...)`-typed value) stored in an array, called DIRECTLY via