authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-10-15 21:28:36+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-10-16 14:00:18+03:00
log14efbf5ed1731058a616582d81223e23f43af128
tree6cf1d08c33dbe1874bc83016df90cc1fbcfd9ede
parent78855bd21866b515018259a2194e036e4b3120df

Sema: fix missing check for tuple default initializers

Closes #17525

2 files changed, 50 insertions(+), 8 deletions(-)

src/Sema.zig+34-8
...@@ -19765,15 +19765,39 @@ fn zirArrayInit(...@@ -19765,15 +19765,39 @@ fn zirArrayInit(
19765 const is_tuple = array_ty.zigTypeTag(mod) == .Struct;19765 const is_tuple = array_ty.zigTypeTag(mod) == .Struct;
19766 const sentinel_val = array_ty.sentinel(mod);19766 const sentinel_val = array_ty.sentinel(mod);
1976719767
19768 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @intFromBool(sentinel_val != null));19768 var root_msg: ?*Module.ErrorMsg = null;
19769 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
19770
19771 const final_len = try sema.usizeCast(block, src, array_ty.arrayLenIncludingSentinel(mod));
19772 const resolved_args = try gpa.alloc(Air.Inst.Ref, final_len);
19769 defer gpa.free(resolved_args);19773 defer gpa.free(resolved_args);
19770 for (args[1..], 0..) |arg, i| {19774 for (resolved_args, 0..) |*dest, i| {
19775 // Less inits than needed.
19776 if (i + 2 > args.len) if (is_tuple) {
19777 const default_val = array_ty.structFieldDefaultValue(i, mod).toIntern();
19778 if (default_val == .unreachable_value) {
19779 const template = "missing tuple field with index {d}";
19780 if (root_msg) |msg| {
19781 try sema.errNote(block, src, msg, template, .{i});
19782 } else {
19783 root_msg = try sema.errMsg(block, src, template, .{i});
19784 }
19785 } else {
19786 dest.* = Air.internedToRef(default_val);
19787 }
19788 continue;
19789 } else {
19790 dest.* = Air.internedToRef(sentinel_val.?.toIntern());
19791 break;
19792 };
19793
19794 const arg = args[i + 1];
19771 const resolved_arg = try sema.resolveInst(arg);19795 const resolved_arg = try sema.resolveInst(arg);
19772 const elem_ty = if (is_tuple)19796 const elem_ty = if (is_tuple)
19773 array_ty.structFieldType(i, mod)19797 array_ty.structFieldType(i, mod)
19774 else19798 else
19775 array_ty.elemType2(mod);19799 array_ty.elemType2(mod);
19776 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {19800 dest.* = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
19777 error.NeededSourceLocation => {19801 error.NeededSourceLocation => {
19778 const decl = mod.declPtr(block.src_decl);19802 const decl = mod.declPtr(block.src_decl);
19779 const elem_src = mod.initSrc(src.node_offset.x, decl, i);19803 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
...@@ -19783,7 +19807,7 @@ fn zirArrayInit(...@@ -19783,7 +19807,7 @@ fn zirArrayInit(
19783 else => return err,19807 else => return err,
19784 };19808 };
19785 if (is_tuple) if (try array_ty.structFieldValueComptime(mod, i)) |field_val| {19809 if (is_tuple) if (try array_ty.structFieldValueComptime(mod, i)) |field_val| {
19786 const init_val = try sema.resolveMaybeUndefVal(resolved_args[i]) orelse {19810 const init_val = try sema.resolveMaybeUndefVal(dest.*) orelse {
19787 const decl = mod.declPtr(block.src_decl);19811 const decl = mod.declPtr(block.src_decl);
19788 const elem_src = mod.initSrc(src.node_offset.x, decl, i);19812 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
19789 return sema.failWithNeededComptime(block, elem_src, .{19813 return sema.failWithNeededComptime(block, elem_src, .{
...@@ -19798,8 +19822,10 @@ fn zirArrayInit(...@@ -19798,8 +19822,10 @@ fn zirArrayInit(
19798 };19822 };
19799 }19823 }
1980019824
19801 if (sentinel_val) |some| {19825 if (root_msg) |msg| {
19802 resolved_args[resolved_args.len - 1] = Air.internedToRef(some.toIntern());19826 try sema.addDeclaredHereNote(msg, array_ty);
19827 root_msg = null;
19828 return sema.failWithOwnedErrorMsg(block, msg);
19803 }19829 }
1980419830
19805 const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| {19831 const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| {
...@@ -19810,7 +19836,7 @@ fn zirArrayInit(...@@ -19810,7 +19836,7 @@ fn zirArrayInit(
19810 const runtime_index = opt_runtime_index orelse {19836 const runtime_index = opt_runtime_index orelse {
19811 const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len);19837 const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len);
19812 for (elem_vals, resolved_args, 0..) |*val, arg, i| {19838 for (elem_vals, resolved_args, 0..) |*val, arg, i| {
19813 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)19839 const elem_ty = if (is_tuple)
19814 array_ty.structFieldType(i, mod)19840 array_ty.structFieldType(i, mod)
19815 else19841 else
19816 array_ty.elemType2(mod);19842 array_ty.elemType2(mod);
...@@ -19845,7 +19871,7 @@ fn zirArrayInit(...@@ -19845,7 +19871,7 @@ fn zirArrayInit(
19845 const alloc = try block.addTy(.alloc, alloc_ty);19871 const alloc = try block.addTy(.alloc, alloc_ty);
19846 const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);19872 const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);
1984719873
19848 if (array_ty.isTuple(mod)) {19874 if (is_tuple) {
19849 for (resolved_args, 0..) |arg, i| {19875 for (resolved_args, 0..) |arg, i| {
19850 const elem_ptr_ty = try sema.ptrType(.{19876 const elem_ptr_ty = try sema.ptrType(.{
19851 .child = array_ty.structFieldType(i, mod).toIntern(),19877 .child = array_ty.structFieldType(i, mod).toIntern(),
test/cases/compile_errors/tuple_init_edge_cases.zig+16
...@@ -45,6 +45,20 @@ pub export fn entry5() void {...@@ -45,6 +45,20 @@ pub export fn entry5() void {
45 var b = T{ .@"0" = 123, .@"2" = 123, .@"1" = 123 };45 var b = T{ .@"0" = 123, .@"2" = 123, .@"1" = 123 };
46 _ = b;46 _ = b;
47}47}
48pub const Consideration = struct {
49 curve: Curve,
50 pub const Curve = union(enum) {
51 logistic: Parameters,
52
53 pub const Parameters = struct { f32, f32, f32, f32 };
54 };
55};
56pub export fn entry6() void {
57 const cons: []Consideration = &.{
58 .{ .curve = .{ .logistic = .{ -7, 1.0, 0 } } },
59 };
60 _ = cons;
61}
4862
49// error63// error
50// backend=stage264// backend=stage2
...@@ -54,3 +68,5 @@ pub export fn entry5() void {...@@ -54,3 +68,5 @@ pub export fn entry5() void {
54// :23:14: error: missing tuple field with index 168// :23:14: error: missing tuple field with index 1
55// :39:14: error: expected at most 2 tuple fields; found 369// :39:14: error: expected at most 2 tuple fields; found 3
56// :45:30: error: index '2' out of bounds of tuple 'struct{comptime comptime_int = 123, u32}'70// :45:30: error: index '2' out of bounds of tuple 'struct{comptime comptime_int = 123, u32}'
71// :58:37: error: missing tuple field with index 3
72// :53:32: note: struct declared here