aboutsummaryrefslogtreecommitdiff
path: root/test/cases/compile_errors
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2023-08-31 14:30:58 +0100
committerAndrew Kelley <andrew@ziglang.org>2023-09-15 11:33:53 -0700
commit88f5315ddfc6eaf3e28433504ec046fb3252db7c (patch)
tree5cd6e8e16b285d136a1fbaa98d12739aeab34feb /test/cases/compile_errors
parent50ef10eb4963167225f7153dc5165292dbac0046 (diff)
downloadzig-88f5315ddfc6eaf3e28433504ec046fb3252db7c.tar.gz
zig-88f5315ddfc6eaf3e28433504ec046fb3252db7c.zip
compiler: implement destructuring syntax
This change implements the following syntax into the compiler: ```zig const x: u32, var y, foo.bar = .{ 1, 2, 3 }; ``` A destructure expression may only appear within a block (i.e. not at comtainer scope). The LHS consists of a sequence of comma-separated var decls and/or lvalue expressions. The RHS is a normal expression. A new result location type, `destructure`, is used, which contains result pointers for each component of the destructure. This means that when the RHS is a more complicated expression, peer type resolution is not used: each result value is individually destructured and written to the result pointers. RLS is always used for destructure expressions, meaning every `const` on the LHS of such an expression creates a true stack allocation. Aside from anonymous array literals, Sema is capable of destructuring the following types: * Tuples * Arrays * Vectors A destructure may be prefixed with the `comptime` keyword, in which case the entire destructure is evaluated at comptime: this means all `var`s in the LHS are `comptime var`s, every lvalue expression is evaluated at comptime, and the RHS is evaluated at comptime. If every LHS is a `const`, this is not allowed: as with single declarations, the user should instead mark the RHS as `comptime`. There are a few subtleties in the grammar changes here. For one thing, if every LHS is an lvalue expression (rather than a var decl), a destructure is considered an expression. This makes, for instance, `if (cond) x, y = .{ 1, 2 };` valid Zig code. A destructure is allowed in almost every context where a standard assignment expression is permitted. The exception is `switch` prongs, which cannot be destructures as the comma is ambiguous with the end of the prong. A follow-up commit will begin utilizing this syntax in the Zig compiler. Resolves: #498
Diffstat (limited to 'test/cases/compile_errors')
-rw-r--r--test/cases/compile_errors/cast_without_result_type.zig7
-rw-r--r--test/cases/compile_errors/extra_comma_in_destructure.zig10
-rw-r--r--test/cases/compile_errors/invalid_destructure_astgen.zig22
-rw-r--r--test/cases/compile_errors/invalid_destructure_sema.zig23
4 files changed, 62 insertions, 0 deletions
diff --git a/test/cases/compile_errors/cast_without_result_type.zig b/test/cases/compile_errors/cast_without_result_type.zig
index 3d8a3d5412..1eaabef474 100644
--- a/test/cases/compile_errors/cast_without_result_type.zig
+++ b/test/cases/compile_errors/cast_without_result_type.zig
@@ -13,6 +13,10 @@ export fn d() void {
var x: f32 = 0;
_ = x + @floatFromInt(123);
}
+export fn e() void {
+ const x: u32, const y: u64 = @intCast(123);
+ _ = x + y;
+}
// error
// backend=stage2
@@ -26,3 +30,6 @@ export fn d() void {
// :9:10: note: use @as to provide explicit result type
// :14:13: error: @floatFromInt must have a known result type
// :14:13: note: use @as to provide explicit result type
+// :17:34: error: @intCast must have a known result type
+// :17:32: note: destructure expressions do not provide a single result type
+// :17:34: note: use @as to provide explicit result type
diff --git a/test/cases/compile_errors/extra_comma_in_destructure.zig b/test/cases/compile_errors/extra_comma_in_destructure.zig
new file mode 100644
index 0000000000..bc848c2ddb
--- /dev/null
+++ b/test/cases/compile_errors/extra_comma_in_destructure.zig
@@ -0,0 +1,10 @@
+export fn foo() void {
+ const x, const y, = .{ 1, 2 };
+ _ = .{ x, y };
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:23: error: expected expression or var decl, found '='
diff --git a/test/cases/compile_errors/invalid_destructure_astgen.zig b/test/cases/compile_errors/invalid_destructure_astgen.zig
new file mode 100644
index 0000000000..b560661176
--- /dev/null
+++ b/test/cases/compile_errors/invalid_destructure_astgen.zig
@@ -0,0 +1,22 @@
+export fn foo() void {
+ const x, const y = .{ 1, 2, 3 };
+ _ = .{ x, y };
+}
+
+export fn bar() void {
+ var x: u32 = undefined;
+ x, const y: u64 = blk: {
+ if (true) break :blk .{ 1, 2 };
+ break :blk .{ .x = 123, .y = 456 };
+ };
+ _ = y;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:25: error: expected 2 elements for destructure, found 3
+// :2:22: note: result destructured here
+// :10:21: error: struct value cannot be destructured
+// :8:21: note: result destructured here
diff --git a/test/cases/compile_errors/invalid_destructure_sema.zig b/test/cases/compile_errors/invalid_destructure_sema.zig
new file mode 100644
index 0000000000..7d2d94598d
--- /dev/null
+++ b/test/cases/compile_errors/invalid_destructure_sema.zig
@@ -0,0 +1,23 @@
+export fn foo() void {
+ const x, const y = 123;
+ _ = .{ x, y };
+}
+
+export fn bar() void {
+ var x: u32 = undefined;
+ x, const y: u64 = blk: {
+ if (false) break :blk .{ 1, 2 };
+ const val = .{ 3, 4, 5 };
+ break :blk val;
+ };
+ _ = y;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:24: error: type 'comptime_int' cannot be destructured
+// :2:22: note: result destructured here
+// :11:20: error: expected 2 elements for destructure, found 3
+// :8:21: note: result destructured here