Optional Fields in toStruct do not get null value
Summary
When a struct contains an optional field without a default value, an arbitrary value is assign (I suspect it is the uninitialized memory).
Possible solution
I noticed that if I change https://github.com/natecraddock/ziglua/blob/6889b2d90ee6ae96810a9f04ec7c62d9aa91d088/src/lib.zig#L4856-L4862
to
if (lua_field_type == .nil) {
if (field.defaultValue()) |default| {
@field(result, field.name) = default;
} else if (field_type_info != .optional) {
return error.LuaTableMissingValue;
} else {
@field(result, field.name) = null;
}
} else {
resolves the issue, but I'm not sure this is the right approach (hence issue and not PR)
Reproducing
Code
const zlua = @import("zlua");
const std = @import("std");
const Lua = zlua.Lua;
const A = struct {
a: ?u64,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
var lua = try Lua.init(allocator);
defer lua.deinit();
try lua.doString("return {a=4};");
std.debug.print("{}\n", .{try lua.toStruct(A, null, false, 1)});
lua.pop(1);
try lua.doString("return {a=nil};");
std.debug.print("{}\n", .{try lua.toStruct(A, null, false, 1)});
lua.pop(1);
}
Expected
main.A{ .a = 4 }
main.A{ .a = null }
Result
main.A{ .a = 4 }
main.A{ .a = 12297829382473034410 }
Workaround
Defining a default value of null circumvent this issue. In the example above:
const A = struct {
a: ?u64 = null,
};
I'd accept a PR with the Possible Solution fix. I'm not sure the API as-written is in a state that I'm completely happy with, given that nullability and gracefully handling type mismatches are fundamental differences between Zig and Lua, but it seems clear that null is intended in this situation and should not require a default value.
That's a good point - on the lua side all the following are equivalent:
A = {a=undefined_variable};
B = {a=nil};
C = {};
So actually defaulting optionals to null might be a footgun that will cover issues in the lua code. However, this is an issue even when default value exists, and I think people usually expect implicit null when using optionals.
I come to think the solution above is the best option. I'll probably submit the PR later this week