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:
@@ -35,7 +35,7 @@ main :: () {
|
||||
print("{}\n", a); // 2
|
||||
print("{}\n", b); // 1
|
||||
|
||||
wrap :: (x: i64) -> (i64) { (x,) }
|
||||
wrap :: (x: i64) -> (i64,) { (x,) } // 1-tuple needs trailing comma; (i64) groups
|
||||
t := wrap(99);
|
||||
print("{}\n", t.0); // 99
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// `?(?i64)` is `optional` wrapping the SINGLE-FIELD TUPLE `(?i64)` — in type
|
||||
// position `(T)` is a 1-tuple, not a grouping (specs.md §"Tuple Types"). So
|
||||
// assigning a bare `?i64` value to a `?(?i64)` slot is a type mismatch: the
|
||||
// optional's payload is the tuple `(?i64)`, not `?i64`.
|
||||
//
|
||||
// Regression (issue 0165): this used to silently lower to a malformed
|
||||
// `insertvalue { {{i64,i1}}, i1 }` that aborted the LLVM verifier. It now
|
||||
// produces a clean diagnostic naming the payload type and pointing at the
|
||||
// parens-are-a-tuple gotcha. (To write a genuine nested optional, alias the
|
||||
// inner one: `Opt :: ?i64; x : ?Opt = ...` — see
|
||||
// examples/optionals/0911-nested-optional-via-alias.sx.)
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
inner : ?i64 = 5;
|
||||
outer : ?(?i64) = inner;
|
||||
print("unreachable\n");
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1,5 +0,0 @@
|
||||
error: cannot assign a value of type '?i64' to optional '?(?i64)': its payload type is '(?i64)' (note: in type position '(T)' is a single-field tuple, not a grouping — write the inner optional without parentheses)
|
||||
--> examples/diagnostics/1195-diagnostics-err-parenthesized-optional-tuple.sx:16:3
|
||||
|
|
||||
16 | outer : ?(?i64) = inner;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File diff suppressed because one or more lines are too long
38
examples/types/0201-types-parenthesized-type-grouping.sx
Normal file
38
examples/types/0201-types-parenthesized-type-grouping.sx
Normal file
@@ -0,0 +1,38 @@
|
||||
// Parenthesized type grouping: in type position `(T)` (single element, no
|
||||
// trailing comma) is a GROUPING that resolves to the inner type — mirroring
|
||||
// value position where `(expr)` groups and `(expr,)` is a 1-tuple. A 1-tuple
|
||||
// type requires the trailing comma `(T,)`; `(A, B)` is a 2-tuple.
|
||||
//
|
||||
// This lets a closure/optional type be parenthesized for readability:
|
||||
// [1](Closure(i64,i64) -> i64) // array of closures (grouped element type)
|
||||
// ?(?i64) // nested optional
|
||||
// without the parens silently turning it into a 1-tuple.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
add :: (a: i64, b: i64) -> i64 { return a + b; }
|
||||
|
||||
main :: () {
|
||||
// `(i64)` groups to `i64`.
|
||||
g : (i64) = 7;
|
||||
print("{}\n", g); // 7
|
||||
// `((i64))` groups twice.
|
||||
gg : ((i64)) = 8;
|
||||
print("{}\n", gg); // 8
|
||||
|
||||
// `?(?i64)` is a genuine nested optional (grouping, not a 1-tuple).
|
||||
no : ?(?i64) = 5;
|
||||
print("{}\n", no!!); // 5
|
||||
|
||||
// Parenthesized closure element type → array of callable closures.
|
||||
fns : [1](Closure(i64, i64) -> i64) = .[ add ];
|
||||
print("{}\n", fns[0](3, 4)); // 7
|
||||
|
||||
// A 1-tuple type still requires the trailing comma.
|
||||
one : (i64,) = (9,);
|
||||
print("{}\n", one.0); // 9
|
||||
|
||||
// A 2-tuple is unaffected.
|
||||
two : (i64, i64) = (40, 2);
|
||||
print("{}\n", two.0 + two.1); // 42
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,6 @@
|
||||
7
|
||||
8
|
||||
5
|
||||
7
|
||||
9
|
||||
42
|
||||
Reference in New Issue
Block a user