Commit 88284c124a

mlugg <mlugg@mlugg.co.uk>
2023-06-26 21:41:42
AstGen: fix result locations for elements of typed array init
Resolves: #16226
1 parent bbda053
Changed files (3)
src
test
behavior
cases
src/AstGen.zig
@@ -1478,9 +1478,26 @@ fn arrayInitExpr(
 
     switch (ri.rl) {
         .discard => {
-            // TODO elements should still be coerced if type is provided
-            for (array_init.ast.elements) |elem_init| {
-                _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
+            if (types.elem != .none) {
+                const elem_ri: ResultInfo = .{ .rl = .{ .ty = types.elem } };
+                for (array_init.ast.elements) |elem_init| {
+                    _ = try expr(gz, scope, elem_ri, elem_init);
+                }
+            } else if (types.array != .none) {
+                for (array_init.ast.elements, 0..) |elem_init, i| {
+                    const elem_ty = try gz.add(.{
+                        .tag = .elem_type_index,
+                        .data = .{ .bin = .{
+                            .lhs = types.array,
+                            .rhs = @enumFromInt(i),
+                        } },
+                    });
+                    _ = try expr(gz, scope, .{ .rl = .{ .ty = elem_ty } }, elem_init);
+                }
+            } else {
+                for (array_init.ast.elements) |elem_init| {
+                    _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
+                }
             }
             return Zir.Inst.Ref.void_value;
         },
@@ -1569,7 +1586,7 @@ fn arrayInitExprInner(
     for (elements, 0..) |elem_init, i| {
         const ri = if (elem_ty != .none)
             ResultInfo{ .rl = .{ .coerced_ty = elem_ty } }
-        else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) ri: {
+        else if (array_ty_inst != .none) ri: {
             const ty_expr = try gz.add(.{
                 .tag = .elem_type_index,
                 .data = .{ .bin = .{
test/behavior/array.zig
@@ -719,3 +719,32 @@ test "pointer to array has ptr field" {
     try std.testing.expect(arr.ptr[3] == 40);
     try std.testing.expect(arr.ptr[4] == 50);
 }
+
+test "discarded array init preserves result location" {
+    const S = struct {
+        fn f(p: *u32) u16 {
+            p.* += 1;
+            return 0;
+        }
+    };
+
+    var x: u32 = 0;
+    _ = [2]u8{
+        @intCast(S.f(&x)),
+        @intCast(S.f(&x)),
+    };
+
+    // Ensure function was run
+    try expect(x == 2);
+}
+
+test "array init with no result location has result type" {
+    const x = .{ .foo = [2]u16{
+        @intCast(10),
+        @intCast(20),
+    } };
+
+    try expect(x.foo.len == 2);
+    try expect(x.foo[0] == 10);
+    try expect(x.foo[1] == 20);
+}
test/cases/compile_errors/discarded_array_bad_elem_type.zig
@@ -0,0 +1,12 @@
+export fn foo() void {
+    _ = [2]u16{
+        "hello",
+        "world",
+    };
+}
+
+// error
+// backend=llvm
+// target=native
+//
+// :3:9: error: expected type 'u16', found '*const [5:0]u8'