authorgravatar for 37453713+ominitay@users.noreply.github.comominitay <37453713+ominitay@users.noreply.github.com> 2022-03-28 12:10:36+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-28 14:10:36+03:00
log25d4c5df706bb8ca6e7882f80d6f8209b9ad31f8
tree102a1619668a9734115f8dd74c17adc70c8c6d46
parent460e7a24451c9bf37a8c1e5e6a4554173416b149
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std.mem.zeroInit: Fix behaviour with empty initialiser


1 files changed, 36 insertions(+), 14 deletions(-)

lib/std/mem.zig+36-14
...@@ -432,6 +432,13 @@ pub fn zeroInit(comptime T: type, init: anytype) T {...@@ -432,6 +432,13 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
432 .Struct => |init_info| {432 .Struct => |init_info| {
433 var value = std.mem.zeroes(T);433 var value = std.mem.zeroes(T);
434434
435 inline for (struct_info.fields) |field| {
436 if (field.default_value) |default_value_ptr| {
437 const default_value = @ptrCast(*const field.field_type, default_value_ptr).*;
438 @field(value, field.name) = default_value;
439 }
440 }
441
435 if (init_info.is_tuple) {442 if (init_info.is_tuple) {
436 inline for (init_info.fields) |field, i| {443 inline for (init_info.fields) |field, i| {
437 @field(value, struct_info.fields[i].name) = @field(init, field.name);444 @field(value, struct_info.fields[i].name) = @field(init, field.name);
...@@ -443,21 +450,14 @@ pub fn zeroInit(comptime T: type, init: anytype) T {...@@ -443,21 +450,14 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
443 if (!@hasField(T, field.name)) {450 if (!@hasField(T, field.name)) {
444 @compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T));451 @compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T));
445 }452 }
446 }
447453
448 inline for (struct_info.fields) |field| {454 switch (@typeInfo(field.field_type)) {
449 if (@hasField(Init, field.name)) {455 .Struct => {
450 switch (@typeInfo(field.field_type)) {456 @field(value, field.name) = zeroInit(field.field_type, @field(init, field.name));
451 .Struct => {457 },
452 @field(value, field.name) = zeroInit(field.field_type, @field(init, field.name));458 else => {
453 },459 @field(value, field.name) = @field(init, field.name);
454 else => {460 },
455 @field(value, field.name) = @field(init, field.name);
456 },
457 }
458 } else if (field.default_value) |default_value_ptr| {
459 const default_value = @ptrCast(*const field.field_type, default_value_ptr).*;
460 @field(value, field.name) = default_value;
461 }461 }
462 }462 }
463463
...@@ -515,6 +515,28 @@ test "zeroInit" {...@@ -515,6 +515,28 @@ test "zeroInit" {
515 .b = 0,515 .b = 0,
516 .a = 0,516 .a = 0,
517 }, c);517 }, c);
518
519 const Foo = struct {
520 foo: u8 = 69,
521 bar: u8,
522 };
523
524 const f = zeroInit(Foo, .{});
525 try testing.expectEqual(Foo{
526 .foo = 69,
527 .bar = 0,
528 }, f);
529
530 const Bar = struct {
531 foo: u32 = 666,
532 bar: u32 = 420,
533 };
534
535 const b = zeroInit(Bar, .{69});
536 try testing.expectEqual(Bar{
537 .foo = 69,
538 .bar = 420,
539 }, b);
518}540}
519541
520/// Compares two slices of numbers lexicographically. O(n).542/// Compares two slices of numbers lexicographically. O(n).