Commit 9a6fa67cbc

Andrew Kelley <andrew@ziglang.org>
2022-03-16 03:21:58
Sema: only do store_ptr tuple optimization for arrays
Check the big comment in the diff for more details. Fixes default-initialization of structs from empty struct literals.
1 parent fd43434
Changed files (3)
src
test
src/Sema.zig
@@ -17578,10 +17578,13 @@ fn storePtr2(
     // To generate better code for tuples, we detect a tuple operand here, and
     // analyze field loads and stores directly. This avoids an extra allocation + memcpy
     // which would occur if we used `coerce`.
-    // However, we avoid this mechanism if the destination element type is
-    // the same tuple as the source, because the regular store will be better for this case.
+    // However, we avoid this mechanism if the destination element type is a tuple,
+    // because the regular store will be better for this case.
+    // If the destination type is a struct we don't want this mechanism to trigger, because
+    // this code does not handle tuple-to-struct coercion which requires dealing with missing
+    // fields.
     const operand_ty = sema.typeOf(uncasted_operand);
-    if (operand_ty.isTuple() and !elem_ty.eql(operand_ty)) {
+    if (operand_ty.isTuple() and elem_ty.zigTypeTag() == .Array) {
         const tuple = operand_ty.tupleFields();
         for (tuple.types) |_, i_usize| {
             const i = @intCast(u32, i_usize);
@@ -17595,6 +17598,7 @@ fn storePtr2(
     }
 
     // TODO do the same thing for anon structs as for tuples above.
+    // However, beware of the need to handle missing/extra fields.
 
     // Detect if we are storing an array operand to a bitcasted vector pointer.
     // If so, we instead reach through the bitcasted pointer to the vector pointer,
test/behavior/struct.zig
@@ -1281,3 +1281,12 @@ test "typed init through error unions and optionals" {
     try S.doTheTest();
     comptime try S.doTheTest();
 }
+
+test "initialize struct with empty literal" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+    const S = struct { x: i32 = 1234 };
+    var s: S = .{};
+    try expect(s.x == 1234);
+}
test/behavior/union.zig
@@ -1092,7 +1092,7 @@ test "@unionInit on union with tag but no fields" {
         }
 
         fn doTheTest() !void {
-            var data: Data = .{ .no_op = .{} };
+            var data: Data = .{ .no_op = {} };
             _ = data;
             var o = Data.decode(&[_]u8{});
             try expectEqual(Type.no_op, o);