authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-22 10:55:41-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-04-22 10:55:41-04:00
log42e81cd81b8a0167c1a21aadf554cea2d882eadd
treee19d5d14323ae797495027f33fbb63120fce660b
parent5da0e0355399acdb0896ad4ac691ecfc9d32222f
parent0e830b16306945ffc74ef95198eb74743ab9f184
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11377 from AnnikaCodes/11368

C backend: Fix array declarations

3 files changed, 81 insertions(+), 32 deletions(-)

src/codegen/c.zig+39-27
...@@ -61,6 +61,11 @@ const FormatTypeAsCIdentContext = struct {...@@ -61,6 +61,11 @@ const FormatTypeAsCIdentContext = struct {
61 mod: *Module,61 mod: *Module,
62};62};
6363
64const ValueRenderLocation = enum {
65 FunctionArgument,
66 Other,
67};
68
64/// TODO make this not cut off at 128 bytes69/// TODO make this not cut off at 128 bytes
65fn formatTypeAsCIdentifier(70fn formatTypeAsCIdentifier(
66 data: FormatTypeAsCIdentContext,71 data: FormatTypeAsCIdentContext,
...@@ -259,7 +264,7 @@ pub const Function = struct {...@@ -259,7 +264,7 @@ pub const Function = struct {
259 0,264 0,
260 );265 );
261 try writer.writeAll(" = ");266 try writer.writeAll(" = ");
262 try f.object.dg.renderValue(writer, ty, val);267 try f.object.dg.renderValue(writer, ty, val, .Other);
263 try writer.writeAll(";\n ");268 try writer.writeAll(";\n ");
264 return decl_c_value;269 return decl_c_value;
265 },270 },
...@@ -298,7 +303,7 @@ pub const Function = struct {...@@ -298,7 +303,7 @@ pub const Function = struct {
298 .constant => |inst| {303 .constant => |inst| {
299 const ty = f.air.typeOf(inst);304 const ty = f.air.typeOf(inst);
300 const val = f.air.value(inst).?;305 const val = f.air.value(inst).?;
301 return f.object.dg.renderValue(w, ty, val);306 return f.object.dg.renderValue(w, ty, val, .Other);
302 },307 },
303 else => return f.object.dg.writeCValue(w, c_value),308 else => return f.object.dg.writeCValue(w, c_value),
304 }309 }
...@@ -310,7 +315,7 @@ pub const Function = struct {...@@ -310,7 +315,7 @@ pub const Function = struct {
310 const ty = f.air.typeOf(inst);315 const ty = f.air.typeOf(inst);
311 const val = f.air.value(inst).?;316 const val = f.air.value(inst).?;
312 try w.writeAll("(*");317 try w.writeAll("(*");
313 try f.object.dg.renderValue(w, ty, val);318 try f.object.dg.renderValue(w, ty, val, .Other);
314 return w.writeByte(')');319 return w.writeByte(')');
315 },320 },
316 else => return f.object.dg.writeCValueDeref(w, c_value),321 else => return f.object.dg.writeCValueDeref(w, c_value),
...@@ -384,7 +389,7 @@ pub const DeclGen = struct {...@@ -384,7 +389,7 @@ pub const DeclGen = struct {
384 try dg.renderTypecast(writer, ty);389 try dg.renderTypecast(writer, ty);
385 try writer.writeAll("){");390 try writer.writeAll("){");
386 var buf: Type.SlicePtrFieldTypeBuffer = undefined;391 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
387 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr());392 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Other);
388 try writer.writeAll(", ");393 try writer.writeAll(", ");
389 try writer.print("{d}", .{val.sliceLen(dg.module)});394 try writer.print("{d}", .{val.sliceLen(dg.module)});
390 try writer.writeAll("}");395 try writer.writeAll("}");
...@@ -544,6 +549,7 @@ pub const DeclGen = struct {...@@ -544,6 +549,7 @@ pub const DeclGen = struct {
544 writer: anytype,549 writer: anytype,
545 ty: Type,550 ty: Type,
546 val: Value,551 val: Value,
552 location: ValueRenderLocation,
547 ) error{ OutOfMemory, AnalysisFail }!void {553 ) error{ OutOfMemory, AnalysisFail }!void {
548 const target = dg.module.getTarget();554 const target = dg.module.getTarget();
549 if (val.isUndefDeep()) {555 if (val.isUndefDeep()) {
...@@ -636,9 +642,9 @@ pub const DeclGen = struct {...@@ -636,9 +642,9 @@ pub const DeclGen = struct {
636 try writer.writeByte('(');642 try writer.writeByte('(');
637 try dg.renderTypecast(writer, ty);643 try dg.renderTypecast(writer, ty);
638 try writer.writeAll("){");644 try writer.writeAll("){");
639 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr);645 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, location);
640 try writer.writeAll(", ");646 try writer.writeAll(", ");
641 try dg.renderValue(writer, Type.usize, slice.len);647 try dg.renderValue(writer, Type.usize, slice.len, location);
642 try writer.writeAll("}");648 try writer.writeAll("}");
643 },649 },
644 .function => {650 .function => {
...@@ -670,7 +676,7 @@ pub const DeclGen = struct {...@@ -670,7 +676,7 @@ pub const DeclGen = struct {
670 try writer.writeByte('{');676 try writer.writeByte('{');
671 const ai = ty.arrayInfo();677 const ai = ty.arrayInfo();
672 if (ai.sentinel) |s| {678 if (ai.sentinel) |s| {
673 try dg.renderValue(writer, ai.elem_type, s);679 try dg.renderValue(writer, ai.elem_type, s, location);
674 }680 }
675 try writer.writeByte('}');681 try writer.writeByte('}');
676 },682 },
...@@ -680,17 +686,23 @@ pub const DeclGen = struct {...@@ -680,17 +686,23 @@ pub const DeclGen = struct {
680 defer arena.deinit();686 defer arena.deinit();
681 const arena_allocator = arena.allocator();687 const arena_allocator = arena.allocator();
682688
689 if (location == .FunctionArgument) {
690 try writer.writeByte('(');
691 try dg.renderTypecast(writer, ty);
692 try writer.writeByte(')');
693 }
694
683 try writer.writeByte('{');695 try writer.writeByte('{');
684 const ai = ty.arrayInfo();696 const ai = ty.arrayInfo();
685 var index: usize = 0;697 var index: usize = 0;
686 while (index < ai.len) : (index += 1) {698 while (index < ai.len) : (index += 1) {
687 if (index != 0) try writer.writeAll(",");699 if (index != 0) try writer.writeAll(",");
688 const elem_val = try val.elemValue(dg.module, arena_allocator, index);700 const elem_val = try val.elemValue(dg.module, arena_allocator, index);
689 try dg.renderValue(writer, ai.elem_type, elem_val);701 try dg.renderValue(writer, ai.elem_type, elem_val, .Other);
690 }702 }
691 if (ai.sentinel) |s| {703 if (ai.sentinel) |s| {
692 if (index != 0) try writer.writeAll(",");704 if (index != 0) try writer.writeAll(",");
693 try dg.renderValue(writer, ai.elem_type, s);705 try dg.renderValue(writer, ai.elem_type, s, .Other);
694 }706 }
695 try writer.writeByte('}');707 try writer.writeByte('}');
696 },708 },
...@@ -701,7 +713,7 @@ pub const DeclGen = struct {...@@ -701,7 +713,7 @@ pub const DeclGen = struct {
701 var opt_buf: Type.Payload.ElemType = undefined;713 var opt_buf: Type.Payload.ElemType = undefined;
702 const payload_type = ty.optionalChild(&opt_buf);714 const payload_type = ty.optionalChild(&opt_buf);
703 if (ty.isPtrLikeOptional()) {715 if (ty.isPtrLikeOptional()) {
704 return dg.renderValue(writer, payload_type, val);716 return dg.renderValue(writer, payload_type, val, location);
705 }717 }
706 if (payload_type.abiSize(target) == 0) {718 if (payload_type.abiSize(target) == 0) {
707 const is_null = val.castTag(.opt_payload) == null;719 const is_null = val.castTag(.opt_payload) == null;
...@@ -713,7 +725,7 @@ pub const DeclGen = struct {...@@ -713,7 +725,7 @@ pub const DeclGen = struct {
713 if (val.castTag(.opt_payload)) |pl| {725 if (val.castTag(.opt_payload)) |pl| {
714 const payload_val = pl.data;726 const payload_val = pl.data;
715 try writer.writeAll(" .is_null = false, .payload = ");727 try writer.writeAll(" .is_null = false, .payload = ");
716 try dg.renderValue(writer, payload_type, payload_val);728 try dg.renderValue(writer, payload_type, payload_val, location);
717 try writer.writeAll(" }");729 try writer.writeAll(" }");
718 } else {730 } else {
719 try writer.writeAll(" .is_null = true }");731 try writer.writeAll(" .is_null = true }");
...@@ -740,7 +752,7 @@ pub const DeclGen = struct {...@@ -740,7 +752,7 @@ pub const DeclGen = struct {
740 if (!payload_type.hasRuntimeBits()) {752 if (!payload_type.hasRuntimeBits()) {
741 // We use the error type directly as the type.753 // We use the error type directly as the type.
742 const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;754 const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;
743 return dg.renderValue(writer, error_type, err_val);755 return dg.renderValue(writer, error_type, err_val, location);
744 }756 }
745757
746 try writer.writeByte('(');758 try writer.writeByte('(');
...@@ -749,11 +761,11 @@ pub const DeclGen = struct {...@@ -749,11 +761,11 @@ pub const DeclGen = struct {
749 if (val.castTag(.eu_payload)) |pl| {761 if (val.castTag(.eu_payload)) |pl| {
750 const payload_val = pl.data;762 const payload_val = pl.data;
751 try writer.writeAll(" .payload = ");763 try writer.writeAll(" .payload = ");
752 try dg.renderValue(writer, payload_type, payload_val);764 try dg.renderValue(writer, payload_type, payload_val, location);
753 try writer.writeAll(", .error = 0 }");765 try writer.writeAll(", .error = 0 }");
754 } else {766 } else {
755 try writer.writeAll(" .error = ");767 try writer.writeAll(" .error = ");
756 try dg.renderValue(writer, error_type, val);768 try dg.renderValue(writer, error_type, val, location);
757 try writer.writeAll(" }");769 try writer.writeAll(" }");
758 }770 }
759 },771 },
...@@ -767,7 +779,7 @@ pub const DeclGen = struct {...@@ -767,7 +779,7 @@ pub const DeclGen = struct {
767 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;779 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
768 if (enum_full.values.count() != 0) {780 if (enum_full.values.count() != 0) {
769 const tag_val = enum_full.values.keys()[field_index];781 const tag_val = enum_full.values.keys()[field_index];
770 return dg.renderValue(writer, enum_full.tag_ty, tag_val);782 return dg.renderValue(writer, enum_full.tag_ty, tag_val, location);
771 } else {783 } else {
772 return writer.print("{d}", .{field_index});784 return writer.print("{d}", .{field_index});
773 }785 }
...@@ -776,7 +788,7 @@ pub const DeclGen = struct {...@@ -776,7 +788,7 @@ pub const DeclGen = struct {
776 const enum_obj = ty.castTag(.enum_numbered).?.data;788 const enum_obj = ty.castTag(.enum_numbered).?.data;
777 if (enum_obj.values.count() != 0) {789 if (enum_obj.values.count() != 0) {
778 const tag_val = enum_obj.values.keys()[field_index];790 const tag_val = enum_obj.values.keys()[field_index];
779 return dg.renderValue(writer, enum_obj.tag_ty, tag_val);791 return dg.renderValue(writer, enum_obj.tag_ty, tag_val, location);
780 } else {792 } else {
781 return writer.print("{d}", .{field_index});793 return writer.print("{d}", .{field_index});
782 }794 }
...@@ -787,7 +799,7 @@ pub const DeclGen = struct {...@@ -787,7 +799,7 @@ pub const DeclGen = struct {
787 else => {799 else => {
788 var int_tag_ty_buffer: Type.Payload.Bits = undefined;800 var int_tag_ty_buffer: Type.Payload.Bits = undefined;
789 const int_tag_ty = ty.intTagType(&int_tag_ty_buffer);801 const int_tag_ty = ty.intTagType(&int_tag_ty_buffer);
790 return dg.renderValue(writer, int_tag_ty, val);802 return dg.renderValue(writer, int_tag_ty, val, location);
791 },803 },
792 }804 }
793 },805 },
...@@ -814,7 +826,7 @@ pub const DeclGen = struct {...@@ -814,7 +826,7 @@ pub const DeclGen = struct {
814 if (!field_ty.hasRuntimeBits()) continue;826 if (!field_ty.hasRuntimeBits()) continue;
815827
816 if (i != 0) try writer.writeAll(",");828 if (i != 0) try writer.writeAll(",");
817 try dg.renderValue(writer, field_ty, field_val);829 try dg.renderValue(writer, field_ty, field_val, location);
818 }830 }
819831
820 try writer.writeAll("}");832 try writer.writeAll("}");
...@@ -831,7 +843,7 @@ pub const DeclGen = struct {...@@ -831,7 +843,7 @@ pub const DeclGen = struct {
831 if (ty.unionTagType()) |tag_ty| {843 if (ty.unionTagType()) |tag_ty| {
832 if (layout.tag_size != 0) {844 if (layout.tag_size != 0) {
833 try writer.writeAll(".tag = ");845 try writer.writeAll(".tag = ");
834 try dg.renderValue(writer, tag_ty, union_obj.tag);846 try dg.renderValue(writer, tag_ty, union_obj.tag, location);
835 try writer.writeAll(", ");847 try writer.writeAll(", ");
836 }848 }
837 try writer.writeAll(".payload = {");849 try writer.writeAll(".payload = {");
...@@ -842,7 +854,7 @@ pub const DeclGen = struct {...@@ -842,7 +854,7 @@ pub const DeclGen = struct {
842 const field_name = ty.unionFields().keys()[index];854 const field_name = ty.unionFields().keys()[index];
843 if (field_ty.hasRuntimeBits()) {855 if (field_ty.hasRuntimeBits()) {
844 try writer.print(".{ } = ", .{fmtIdent(field_name)});856 try writer.print(".{ } = ", .{fmtIdent(field_name)});
845 try dg.renderValue(writer, field_ty, union_obj.val);857 try dg.renderValue(writer, field_ty, union_obj.val, location);
846 }858 }
847 if (ty.unionTagType()) |_| {859 if (ty.unionTagType()) |_| {
848 try writer.writeAll("}");860 try writer.writeAll("}");
...@@ -988,7 +1000,7 @@ pub const DeclGen = struct {...@@ -988,7 +1000,7 @@ pub const DeclGen = struct {
988 }1000 }
989 if (ptr_sentinel) |s| {1001 if (ptr_sentinel) |s| {
990 try bw.writeAll("_s_");1002 try bw.writeAll("_s_");
991 try dg.renderValue(bw, child_type, s);1003 try dg.renderValue(bw, child_type, s, .Other);
992 }1004 }
993 try bw.writeAll(";\n");1005 try bw.writeAll(";\n");
9941006
...@@ -1629,7 +1641,7 @@ pub fn genDecl(o: *Object) !void {...@@ -1629,7 +1641,7 @@ pub fn genDecl(o: *Object) !void {
1629 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");1641 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
1630 try w.writeAll(" = ");1642 try w.writeAll(" = ");
1631 if (variable.init.tag() != .unreachable_value) {1643 if (variable.init.tag() != .unreachable_value) {
1632 try o.dg.renderValue(w, tv.ty, variable.init);1644 try o.dg.renderValue(w, tv.ty, variable.init, .Other);
1633 }1645 }
1634 try w.writeAll(";");1646 try w.writeAll(";");
1635 try o.indent_writer.insertNewline();1647 try o.indent_writer.insertNewline();
...@@ -1644,7 +1656,7 @@ pub fn genDecl(o: *Object) !void {...@@ -1644,7 +1656,7 @@ pub fn genDecl(o: *Object) !void {
1644 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");1656 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");
16451657
1646 try writer.writeAll(" = ");1658 try writer.writeAll(" = ");
1647 try o.dg.renderValue(writer, tv.ty, tv.val);1659 try o.dg.renderValue(writer, tv.ty, tv.val, .Other);
1648 try writer.writeAll(";\n");1660 try writer.writeAll(";\n");
1649 }1661 }
1650}1662}
...@@ -2748,7 +2760,7 @@ fn airCall(...@@ -2748,7 +2760,7 @@ fn airCall(
2748 try writer.writeAll(", ");2760 try writer.writeAll(", ");
2749 }2761 }
2750 if (f.air.value(arg)) |val| {2762 if (f.air.value(arg)) |val| {
2751 try f.object.dg.renderValue(writer, f.air.typeOf(arg), val);2763 try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument);
2752 } else {2764 } else {
2753 const val = try f.resolveInst(arg);2765 const val = try f.resolveInst(arg);
2754 try f.writeCValue(writer, val);2766 try f.writeCValue(writer, val);
...@@ -2964,7 +2976,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2964,7 +2976,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
2964 for (items) |item| {2976 for (items) |item| {
2965 try f.object.indent_writer.insertNewline();2977 try f.object.indent_writer.insertNewline();
2966 try writer.writeAll("case ");2978 try writer.writeAll("case ");
2967 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?);2979 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);
2968 try writer.writeAll(": ");2980 try writer.writeAll(": ");
2969 }2981 }
2970 // The case body must be noreturn so we don't need to insert a break.2982 // The case body must be noreturn so we don't need to insert a break.
...@@ -3414,14 +3426,14 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3414,14 +3426,14 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
3414 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3426 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3415 try f.writeCValueDeref(writer, operand);3427 try f.writeCValueDeref(writer, operand);
3416 try writer.writeAll(" = ");3428 try writer.writeAll(" = ");
3417 try f.object.dg.renderValue(writer, error_ty, Value.zero);3429 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
3418 try writer.writeAll(";\n ");3430 try writer.writeAll(";\n ");
34193431
3420 return operand;3432 return operand;
3421 }3433 }
3422 try f.writeCValueDeref(writer, operand);3434 try f.writeCValueDeref(writer, operand);
3423 try writer.writeAll(".error = ");3435 try writer.writeAll(".error = ");
3424 try f.object.dg.renderValue(writer, error_ty, Value.zero);3436 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
3425 try writer.writeAll(";\n");3437 try writer.writeAll(";\n");
34263438
3427 // Then return the payload pointer (only if it is used)3439 // Then return the payload pointer (only if it is used)
test/behavior/array.zig+17-1
...@@ -148,7 +148,7 @@ test "void arrays" {...@@ -148,7 +148,7 @@ test "void arrays" {
148 try expect(array.len == 4);148 try expect(array.len == 4);
149}149}
150150
151test "nested arrays" {151test "nested arrays of strings" {
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
154154
...@@ -162,6 +162,22 @@ test "nested arrays" {...@@ -162,6 +162,22 @@ test "nested arrays" {
162 }162 }
163}163}
164164
165test "nested arrays of integers" {
166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
168 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
169
170 const array_of_numbers = [_][2]u8{
171 [2]u8{ 1, 2 },
172 [2]u8{ 3, 4 },
173 };
174
175 try expect(array_of_numbers[0][0] == 1);
176 try expect(array_of_numbers[0][1] == 2);
177 try expect(array_of_numbers[1][0] == 3);
178 try expect(array_of_numbers[1][1] == 4);
179}
180
165test "implicit comptime in array type size" {181test "implicit comptime in array type size" {
166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/fn.zig+25-4
...@@ -349,10 +349,9 @@ fn numberLiteralArg(a: anytype) !void {...@@ -349,10 +349,9 @@ fn numberLiteralArg(a: anytype) !void {
349}349}
350350
351test "function call with anon list literal" {351test "function call with anon list literal" {
352 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO352 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
353 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
354 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;354 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
356355
357 const S = struct {356 const S = struct {
358 fn doTheTest() !void {357 fn doTheTest() !void {
...@@ -369,6 +368,28 @@ test "function call with anon list literal" {...@@ -369,6 +368,28 @@ test "function call with anon list literal" {
369 comptime try S.doTheTest();368 comptime try S.doTheTest();
370}369}
371370
371test "function call with anon list literal - 2D" {
372 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
373 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
374 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
376
377 const S = struct {
378 fn doTheTest() !void {
379 try consumeVec(.{ .{ 9, 8 }, .{ 7, 6 } });
380 }
381
382 fn consumeVec(vec: [2][2]f32) !void {
383 try expect(vec[0][0] == 9);
384 try expect(vec[0][1] == 8);
385 try expect(vec[1][0] == 7);
386 try expect(vec[1][1] == 6);
387 }
388 };
389 try S.doTheTest();
390 comptime try S.doTheTest();
391}
392
372test "ability to give comptime types and non comptime types to same parameter" {393test "ability to give comptime types and non comptime types to same parameter" {
373 const S = struct {394 const S = struct {
374 fn doTheTest() !void {395 fn doTheTest() !void {