authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-26 14:47:43-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-26 14:47:43-05:00
logb3aa1ab693ac160a07c44f07c7b90577039860a1
tree6c5f4bf623b276963cec98ebbf713d2a752e9e01
parentdb82c1b9820449f2d1e6ef54dd32ec3ffd3c583f
parent315d4e84425ddff888de8d464f657981e4c45da7
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10994 from Vexu/typeof-scope

stage2: `@TypeOf` improvements

7 files changed, 158 insertions(+), 52 deletions(-)

src/AstGen.zig+41-15
...@@ -2159,6 +2159,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2159,6 +2159,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2159 .negate,2159 .negate,
2160 .negate_wrap,2160 .negate_wrap,
2161 .typeof,2161 .typeof,
2162 .typeof_builtin,
2162 .xor,2163 .xor,
2163 .optional_type,2164 .optional_type,
2164 .optional_payload_safe,2165 .optional_payload_safe,
...@@ -6875,29 +6876,54 @@ fn typeOf(...@@ -6875,29 +6876,54 @@ fn typeOf(
6875 scope: *Scope,6876 scope: *Scope,
6876 rl: ResultLoc,6877 rl: ResultLoc,
6877 node: Ast.Node.Index,6878 node: Ast.Node.Index,
6878 params: []const Ast.Node.Index,6879 args: []const Ast.Node.Index,
6879) InnerError!Zir.Inst.Ref {6880) InnerError!Zir.Inst.Ref {
6880 if (params.len < 1) {6881 if (args.len < 1) {
6881 return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{});6882 return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{});
6882 }6883 }
6883 if (params.len == 1) {6884 const gpa = gz.astgen.gpa;
6884 const expr_result = try reachableExpr(gz, scope, .none, params[0], node);6885 if (args.len == 1) {
6885 const result = try gz.addUnNode(.typeof, expr_result, node);6886 const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node);
6886 return rvalue(gz, rl, result, node);6887
6888 var typeof_scope = gz.makeSubBlock(scope);
6889 typeof_scope.force_comptime = false;
6890 defer typeof_scope.unstack();
6891
6892 const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, args[0], node);
6893 if (!gz.refIsNoReturn(ty_expr)) {
6894 _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr);
6895 }
6896 try typeof_scope.setBlockBody(typeof_inst);
6897
6898 // typeof_scope unstacked now, can add new instructions to gz
6899 try gz.instructions.append(gpa, typeof_inst);
6900 return rvalue(gz, rl, indexToRef(typeof_inst), node);
6887 }6901 }
6902 const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len;
6903 const payload_index = try reserveExtra(gz.astgen, payload_size + args.len);
6904 var args_index = payload_index + payload_size;
6905
6906 const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len);
68886907
6889 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{6908 var typeof_scope = gz.makeSubBlock(scope);
6909 typeof_scope.force_comptime = false;
6910
6911 for (args) |arg, i| {
6912 const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node);
6913 gz.astgen.extra.items[args_index + i] = @enumToInt(param_ref);
6914 }
6915 _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value);
6916
6917 const body = typeof_scope.instructionsSlice();
6918 gz.astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{
6919 .body_len = @intCast(u32, body.len),
6920 .body_index = @intCast(u32, gz.astgen.extra.items.len),
6890 .src_node = gz.nodeIndexToRelative(node),6921 .src_node = gz.nodeIndexToRelative(node),
6891 });6922 });
6892 var extra_index = try reserveExtra(gz.astgen, params.len);6923 try gz.astgen.extra.appendSlice(gpa, body);
6893 for (params) |param| {6924 typeof_scope.unstack();
6894 const param_ref = try reachableExpr(gz, scope, .none, param, node);
6895 gz.astgen.extra.items[extra_index] = @enumToInt(param_ref);
6896 extra_index += 1;
6897 }
68986925
6899 const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len);6926 return rvalue(gz, rl, typeof_inst, node);
6900 return rvalue(gz, rl, result, node);
6901}6927}
69026928
6903fn builtinCall(6929fn builtinCall(
src/Sema.zig+46-3
...@@ -124,6 +124,7 @@ pub const Block = struct {...@@ -124,6 +124,7 @@ pub const Block = struct {
124 runtime_index: u32 = 0,124 runtime_index: u32 = 0,
125125
126 is_comptime: bool,126 is_comptime: bool,
127 is_typeof: bool = false,
127128
128 /// when null, it is determined by build mode, changed by @setRuntimeSafety129 /// when null, it is determined by build mode, changed by @setRuntimeSafety
129 want_safety: ?bool = null,130 want_safety: ?bool = null,
...@@ -181,6 +182,7 @@ pub const Block = struct {...@@ -181,6 +182,7 @@ pub const Block = struct {
181 .label = null,182 .label = null,
182 .inlining = parent.inlining,183 .inlining = parent.inlining,
183 .is_comptime = parent.is_comptime,184 .is_comptime = parent.is_comptime,
185 .is_typeof = parent.is_typeof,
184 .runtime_cond = parent.runtime_cond,186 .runtime_cond = parent.runtime_cond,
185 .runtime_loop = parent.runtime_loop,187 .runtime_loop = parent.runtime_loop,
186 .runtime_index = parent.runtime_index,188 .runtime_index = parent.runtime_index,
...@@ -682,6 +684,7 @@ fn analyzeBodyInner(...@@ -682,6 +684,7 @@ fn analyzeBodyInner(
682 .size_of => try sema.zirSizeOf(block, inst),684 .size_of => try sema.zirSizeOf(block, inst),
683 .bit_size_of => try sema.zirBitSizeOf(block, inst),685 .bit_size_of => try sema.zirBitSizeOf(block, inst),
684 .typeof => try sema.zirTypeof(block, inst),686 .typeof => try sema.zirTypeof(block, inst),
687 .typeof_builtin => try sema.zirTypeofBuiltin(block, inst),
685 .log2_int_type => try sema.zirLog2IntType(block, inst),688 .log2_int_type => try sema.zirLog2IntType(block, inst),
686 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),689 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
687 .xor => try sema.zirBitwise(block, inst, .xor),690 .xor => try sema.zirBitwise(block, inst, .xor),
...@@ -10574,6 +10577,29 @@ fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -10574,6 +10577,29 @@ fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
10574 return sema.addType(operand_ty);10577 return sema.addType(operand_ty);
10575}10578}
1057610579
10580fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10581 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
10582 const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);
10583 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
10584
10585 var child_block: Block = .{
10586 .parent = block,
10587 .sema = sema,
10588 .src_decl = block.src_decl,
10589 .namespace = block.namespace,
10590 .wip_capture_scope = block.wip_capture_scope,
10591 .instructions = .{},
10592 .inlining = block.inlining,
10593 .is_comptime = false,
10594 .is_typeof = true,
10595 };
10596 defer child_block.instructions.deinit(sema.gpa);
10597
10598 const operand = try sema.resolveBody(&child_block, body, inst);
10599 const operand_ty = sema.typeOf(operand);
10600 return sema.addType(operand_ty);
10601}
10602
10577fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10603fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10578 const inst_data = sema.code.instructions.items(.data)[inst].un_node;10604 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
10579 const src = inst_data.src();10605 const src = inst_data.src();
...@@ -10624,8 +10650,24 @@ fn zirTypeofPeer(...@@ -10624,8 +10650,24 @@ fn zirTypeofPeer(
10624 const tracy = trace(@src());10650 const tracy = trace(@src());
10625 defer tracy.end();10651 defer tracy.end();
1062610652
10627 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);10653 const extra = sema.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
10628 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };10654 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
10655 const body = sema.code.extra[extra.data.body_index..][0..extra.data.body_len];
10656
10657 var child_block: Block = .{
10658 .parent = block,
10659 .sema = sema,
10660 .src_decl = block.src_decl,
10661 .namespace = block.namespace,
10662 .wip_capture_scope = block.wip_capture_scope,
10663 .instructions = .{},
10664 .inlining = block.inlining,
10665 .is_comptime = false,
10666 .is_typeof = true,
10667 };
10668 defer child_block.instructions.deinit(sema.gpa);
10669 _ = try sema.analyzeBody(&child_block, body);
10670
10629 const args = sema.code.refSlice(extra.end, extended.small);10671 const args = sema.code.refSlice(extra.end, extended.small);
1063010672
10631 const inst_list = try sema.gpa.alloc(Air.Inst.Ref, args.len);10673 const inst_list = try sema.gpa.alloc(Air.Inst.Ref, args.len);
...@@ -13385,7 +13427,7 @@ fn zirBuiltinExtern(...@@ -13385,7 +13427,7 @@ fn zirBuiltinExtern(
13385}13427}
1338613428
13387fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void {13429fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
13388 if (sema.func == null) {13430 if (sema.func == null and !block.is_typeof) {
13389 return sema.fail(block, src, "instruction illegal outside function body", .{});13431 return sema.fail(block, src, "instruction illegal outside function body", .{});
13390 }13432 }
13391}13433}
...@@ -14152,7 +14194,8 @@ fn fieldCallBind(...@@ -14152,7 +14194,8 @@ fn fieldCallBind(
14152 if (first_param_tag == .var_args_param or14194 if (first_param_tag == .var_args_param or
14153 first_param_tag == .generic_poison or (14195 first_param_tag == .generic_poison or (
14154 first_param_type.zigTypeTag() == .Pointer and14196 first_param_type.zigTypeTag() == .Pointer and
14155 first_param_type.ptrSize() == .One and14197 (first_param_type.ptrSize() == .One or
14198 first_param_type.ptrSize() == .C) and
14156 first_param_type.childType().eql(concrete_ty)))14199 first_param_type.childType().eql(concrete_ty)))
14157 {14200 {
14158 // zig fmt: on14201 // zig fmt: on
src/Zir.zig+11
...@@ -547,6 +547,9 @@ pub const Inst = struct {...@@ -547,6 +547,9 @@ pub const Inst = struct {
547 /// Returns the type of a value.547 /// Returns the type of a value.
548 /// Uses the `un_node` field.548 /// Uses the `un_node` field.
549 typeof,549 typeof,
550 /// Implements `@TypeOf` for one operand.
551 /// Uses the `pl_node` field.
552 typeof_builtin,
550 /// Given a value, look at the type of it, which must be an integer type.553 /// Given a value, look at the type of it, which must be an integer type.
551 /// Returns the integer type for the RHS of a shift operation.554 /// Returns the integer type for the RHS of a shift operation.
552 /// Uses the `un_node` field.555 /// Uses the `un_node` field.
...@@ -1067,6 +1070,7 @@ pub const Inst = struct {...@@ -1067,6 +1070,7 @@ pub const Inst = struct {
1067 .negate,1070 .negate,
1068 .negate_wrap,1071 .negate_wrap,
1069 .typeof,1072 .typeof,
1073 .typeof_builtin,
1070 .xor,1074 .xor,
1071 .optional_type,1075 .optional_type,
1072 .optional_payload_safe,1076 .optional_payload_safe,
...@@ -1429,6 +1433,7 @@ pub const Inst = struct {...@@ -1429,6 +1433,7 @@ pub const Inst = struct {
1429 .ptr_cast = .pl_node,1433 .ptr_cast = .pl_node,
1430 .truncate = .pl_node,1434 .truncate = .pl_node,
1431 .align_cast = .pl_node,1435 .align_cast = .pl_node,
1436 .typeof_builtin = .pl_node,
14321437
1433 .has_decl = .pl_node,1438 .has_decl = .pl_node,
1434 .has_field = .pl_node,1439 .has_field = .pl_node,
...@@ -2391,6 +2396,12 @@ pub const Inst = struct {...@@ -2391,6 +2396,12 @@ pub const Inst = struct {
2391 };2396 };
2392 };2397 };
23932398
2399 pub const TypeOfPeer = struct {
2400 src_node: i32,
2401 body_len: u32,
2402 body_index: u32,
2403 };
2404
2394 pub const BuiltinCall = struct {2405 pub const BuiltinCall = struct {
2395 options: Ref,2406 options: Ref,
2396 callee: Ref,2407 callee: Ref,
src/print_zir.zig+16-3
...@@ -374,6 +374,7 @@ const Writer = struct {...@@ -374,6 +374,7 @@ const Writer = struct {
374 .validate_array_init,374 .validate_array_init,
375 .validate_array_init_comptime,375 .validate_array_init_comptime,
376 .c_import,376 .c_import,
377 .typeof_builtin,
377 => try self.writePlNodeBlock(stream, inst),378 => try self.writePlNodeBlock(stream, inst),
378379
379 .condbr,380 .condbr,
...@@ -458,9 +459,8 @@ const Writer = struct {...@@ -458,9 +459,8 @@ const Writer = struct {
458 .variable => try self.writeVarExtended(stream, extended),459 .variable => try self.writeVarExtended(stream, extended),
459 .alloc => try self.writeAllocExtended(stream, extended),460 .alloc => try self.writeAllocExtended(stream, extended),
460461
461 .compile_log,462 .compile_log => try self.writeNodeMultiOp(stream, extended),
462 .typeof_peer,463 .typeof_peer => try self.writeTypeofPeer(stream, extended),
463 => try self.writeNodeMultiOp(stream, extended),
464464
465 .add_with_overflow,465 .add_with_overflow,
466 .sub_with_overflow,466 .sub_with_overflow,
...@@ -1966,6 +1966,19 @@ const Writer = struct {...@@ -1966,6 +1966,19 @@ const Writer = struct {
1966 try self.writeSrc(stream, src);1966 try self.writeSrc(stream, src);
1967 }1967 }
19681968
1969 fn writeTypeofPeer(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
1970 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
1971 const body = self.code.extra[extra.data.body_index..][0..extra.data.body_len];
1972 try self.writeBracedBody(stream, body);
1973 try stream.writeAll(",[");
1974 const args = self.code.refSlice(extra.end, extended.small);
1975 for (args) |arg, i| {
1976 if (i != 0) try stream.writeAll(", ");
1977 try self.writeInstRef(stream, arg);
1978 }
1979 try stream.writeAll("])");
1980 }
1981
1969 fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1982 fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1970 const inst_data = self.code.instructions.items(.data)[inst].bool_br;1983 const inst_data = self.code.instructions.items(.data)[inst].bool_br;
1971 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);1984 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
test/behavior.zig+2-2
...@@ -38,6 +38,7 @@ test {...@@ -38,6 +38,7 @@ test {
38 _ = @import("behavior/bugs/3112.zig");38 _ = @import("behavior/bugs/3112.zig");
39 _ = @import("behavior/bugs/3367.zig");39 _ = @import("behavior/bugs/3367.zig");
40 _ = @import("behavior/bugs/3586.zig");40 _ = @import("behavior/bugs/3586.zig");
41 _ = @import("behavior/bugs/4328.zig");
41 _ = @import("behavior/bugs/4560.zig");42 _ = @import("behavior/bugs/4560.zig");
42 _ = @import("behavior/bugs/4769_a.zig");43 _ = @import("behavior/bugs/4769_a.zig");
43 _ = @import("behavior/bugs/4769_b.zig");44 _ = @import("behavior/bugs/4769_b.zig");
...@@ -102,6 +103,7 @@ test {...@@ -102,6 +103,7 @@ test {
102 builtin.zig_backend != .stage2_wasm)103 builtin.zig_backend != .stage2_wasm)
103 {104 {
104 // Tests that pass for stage1, llvm backend, C backend105 // Tests that pass for stage1, llvm backend, C backend
106 _ = @import("behavior/bugs/5474.zig");
105 _ = @import("behavior/bugs/9584.zig");107 _ = @import("behavior/bugs/9584.zig");
106 _ = @import("behavior/bugs/10970.zig");108 _ = @import("behavior/bugs/10970.zig");
107 _ = @import("behavior/cast_int.zig");109 _ = @import("behavior/cast_int.zig");
...@@ -149,10 +151,8 @@ test {...@@ -149,10 +151,8 @@ test {
149 _ = @import("behavior/bugs/1851.zig");151 _ = @import("behavior/bugs/1851.zig");
150 _ = @import("behavior/bugs/3384.zig");152 _ = @import("behavior/bugs/3384.zig");
151 _ = @import("behavior/bugs/3779.zig");153 _ = @import("behavior/bugs/3779.zig");
152 _ = @import("behavior/bugs/4328.zig");
153 _ = @import("behavior/bugs/5398.zig");154 _ = @import("behavior/bugs/5398.zig");
154 _ = @import("behavior/bugs/5413.zig");155 _ = @import("behavior/bugs/5413.zig");
155 _ = @import("behavior/bugs/5474.zig");
156 _ = @import("behavior/bugs/5487.zig");156 _ = @import("behavior/bugs/5487.zig");
157 _ = @import("behavior/bugs/6456.zig");157 _ = @import("behavior/bugs/6456.zig");
158 _ = @import("behavior/bugs/6781.zig");158 _ = @import("behavior/bugs/6781.zig");
test/behavior/bugs/4328.zig+16-7
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const expectEqual = @import("std").testing.expectEqual;1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
23
3const FILE = extern struct {4const FILE = extern struct {
4 dummy_field: u8,5 dummy_field: u8,
...@@ -16,18 +17,20 @@ const S = extern struct {...@@ -16,18 +17,20 @@ const S = extern struct {
16};17};
1718
18test "Extern function calls in @TypeOf" {19test "Extern function calls in @TypeOf" {
20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
21
19 const Test = struct {22 const Test = struct {
20 fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) {23 fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) {
21 return 0;24 return 0;
22 }25 }
2326
24 fn test_fn_2(a: anytype) @TypeOf((S{ .state = 0 }).s_do_thing(a)) {27 fn test_fn_2(s: anytype, a: anytype) @TypeOf(s.s_do_thing(a)) {
25 return 1;28 return 1;
26 }29 }
2730
28 fn doTheTest() !void {31 fn doTheTest() !void {
29 try expectEqual(c_int, @TypeOf(test_fn_1(0, 42)));32 try expect(@TypeOf(test_fn_1(0, 42)) == c_int);
30 try expectEqual(c_short, @TypeOf(test_fn_2(0)));33 try expect(@TypeOf(test_fn_2(&S{ .state = 1 }, 0)) == c_short);
31 }34 }
32 };35 };
3336
...@@ -36,13 +39,15 @@ test "Extern function calls in @TypeOf" {...@@ -36,13 +39,15 @@ test "Extern function calls in @TypeOf" {
36}39}
3740
38test "Peer resolution of extern function calls in @TypeOf" {41test "Peer resolution of extern function calls in @TypeOf" {
42 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
43
39 const Test = struct {44 const Test = struct {
40 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {45 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
41 return 0;46 return 0;
42 }47 }
4348
44 fn doTheTest() !void {49 fn doTheTest() !void {
45 try expectEqual(c_long, @TypeOf(test_fn()));50 try expect(@TypeOf(test_fn()) == c_long);
46 }51 }
47 };52 };
4853
...@@ -51,6 +56,10 @@ test "Peer resolution of extern function calls in @TypeOf" {...@@ -51,6 +56,10 @@ test "Peer resolution of extern function calls in @TypeOf" {
51}56}
5257
53test "Extern function calls, dereferences and field access in @TypeOf" {58test "Extern function calls, dereferences and field access in @TypeOf" {
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
61 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
62
54 const Test = struct {63 const Test = struct {
55 fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) {64 fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) {
56 _ = a;65 _ = a;
...@@ -63,8 +72,8 @@ test "Extern function calls, dereferences and field access in @TypeOf" {...@@ -63,8 +72,8 @@ test "Extern function calls, dereferences and field access in @TypeOf" {
63 }72 }
6473
65 fn doTheTest() !void {74 fn doTheTest() !void {
66 try expectEqual(FILE, @TypeOf(test_fn_1(0)));75 try expect(@TypeOf(test_fn_1(0)) == FILE);
67 try expectEqual(u8, @TypeOf(test_fn_2(0)));76 try expect(@TypeOf(test_fn_2(0)) == u8);
68 }77 }
69 };78 };
7079
test/behavior/bugs/5474.zig+26-22
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
23
3// baseline (control) struct with array of scalar4// baseline (control) struct with array of scalar
4const Box0 = struct {5const Box0 = struct {
...@@ -25,33 +26,36 @@ const Box2 = struct {...@@ -25,33 +26,36 @@ const Box2 = struct {
25 };26 };
26};27};
2728
28fn doTest() !void {29fn mutable() !void {
29 // var30 var box0: Box0 = .{ .items = undefined };
30 {31 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false);
31 var box0: Box0 = .{ .items = undefined };
32 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false);
3332
34 var box1: Box1 = .{ .items = undefined };33 var box1: Box1 = .{ .items = undefined };
35 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false);34 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false);
3635
37 var box2: Box2 = .{ .items = undefined };36 var box2: Box2 = .{ .items = undefined };
38 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false);37 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false);
39 }38}
39
40fn constant() !void {
41 const box0: Box0 = .{ .items = undefined };
42 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true);
4043
41 // const44 const box1: Box1 = .{ .items = undefined };
42 {45 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true);
43 const box0: Box0 = .{ .items = undefined };
44 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true);
4546
46 const box1: Box1 = .{ .items = undefined };47 const box2: Box2 = .{ .items = undefined };
47 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true);48 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true);
49}
4850
49 const box2: Box2 = .{ .items = undefined };51test "pointer-to-array constness for zero-size elements, var" {
50 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true);52 try mutable();
51 }53 comptime try mutable();
52}54}
5355
54test "pointer-to-array constness for zero-size elements" {56test "pointer-to-array constness for zero-size elements, const" {
55 try doTest();57 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
56 comptime try doTest();58
59 try constant();
60 comptime try constant();
57}61}