From 9a6fa67cbc7e5771f3770c0cb7d6d2c6bafb6957 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 15 Mar 2022 19:21:58 -0700 Subject: [PATCH] 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. --- src/Sema.zig | 10 +++++++--- test/behavior/struct.zig | 9 +++++++++ test/behavior/union.zig | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index fb2b187c60..e7b4517590 100644 --- a/src/Sema.zig +++ b/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, diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index abd24967bb..8383b81cd5 100644 --- a/test/behavior/struct.zig +++ b/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); +} diff --git a/test/behavior/union.zig b/test/behavior/union.zig index bcd2575414..74df2bf4e4 100644 --- a/test/behavior/union.zig +++ b/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);