authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-03-05 12:39:32+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-12 12:06:19-04:00
logccf670c2b04ebeb9db43eb9f5c47c6cf03e4b1d0
tree3f7899bf6231500782af185ffe701ee66793e226
parent602029bb2fb78048e46136784e717b57b8de8f2c

Zir: implement explicit block_comptime instruction

Resolves: #7056

18 files changed, 234 insertions(+), 304 deletions(-)

lib/std/Build/Cache.zig+2-2
......@@ -374,7 +374,7 @@ pub const Manifest = struct {
374374 self.failed_file_index = null;
375375
376376 const ext = ".txt";
377 var manifest_file_path: [self.hex_digest.len + ext.len]u8 = undefined;
377 var manifest_file_path: [hex_digest_len + ext.len]u8 = undefined;
378378
379379 var bin_digest: BinDigest = undefined;
380380 self.hash.hasher.final(&bin_digest);
......@@ -389,7 +389,7 @@ pub const Manifest = struct {
389389 self.hash.hasher.update(&bin_digest);
390390
391391 mem.copy(u8, &manifest_file_path, &self.hex_digest);
392 manifest_file_path[self.hex_digest.len..][0..ext.len].* = ext.*;
392 manifest_file_path[hex_digest_len..][0..ext.len].* = ext.*;
393393
394394 if (self.files.items.len == 0) {
395395 // If there are no file inputs, we check if the manifest file exists instead of
lib/std/crypto/25519/ed25519.zig+1-1
......@@ -622,7 +622,7 @@ test "ed25519 test vectors" {
622622 },
623623 };
624624 for (entries) |entry| {
625 var msg: [entry.msg_hex.len / 2]u8 = undefined;
625 var msg: [64 / 2]u8 = undefined;
626626 _ = try fmt.hexToBytes(&msg, entry.msg_hex);
627627 var public_key_bytes: [32]u8 = undefined;
628628 _ = try fmt.hexToBytes(&public_key_bytes, entry.public_key_hex);
lib/std/enums.zig+4-4
......@@ -177,9 +177,9 @@ test "std.enums.directEnumArrayDefault slice" {
177177/// Cast an enum literal, value, or string to the enum value of type E
178178/// with the same name.
179179pub fn nameCast(comptime E: type, comptime value: anytype) E {
180 comptime {
180 return comptime blk: {
181181 const V = @TypeOf(value);
182 if (V == E) return value;
182 if (V == E) break :blk value;
183183 var name: ?[]const u8 = switch (@typeInfo(V)) {
184184 .EnumLiteral, .Enum => @tagName(value),
185185 .Pointer => if (std.meta.trait.isZigString(V)) value else null,
......@@ -187,12 +187,12 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E {
187187 };
188188 if (name) |n| {
189189 if (@hasField(E, n)) {
190 return @field(E, n);
190 break :blk @field(E, n);
191191 }
192192 @compileError("Enum " ++ @typeName(E) ++ " has no field named " ++ n);
193193 }
194194 @compileError("Cannot cast from " ++ @typeName(@TypeOf(value)) ++ " to " ++ @typeName(E));
195 }
195 };
196196}
197197
198198test "std.enums.nameCast" {
lib/std/math.zig+1-1
......@@ -877,7 +877,7 @@ fn testDivFloor() !void {
877877/// zero.
878878pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T {
879879 @setRuntimeSafety(false);
880 if (comptime std.meta.trait.isNumber(T) and denominator == 0) return error.DivisionByZero;
880 if ((comptime std.meta.trait.isNumber(T)) and denominator == 0) return error.DivisionByZero;
881881 const info = @typeInfo(T);
882882 switch (info) {
883883 .ComptimeFloat, .Float => return @ceil(numerator / denominator),
lib/std/meta.zig+6-6
......@@ -549,14 +549,14 @@ test "std.meta.FieldType" {
549549}
550550
551551pub fn fieldNames(comptime T: type) *const [fields(T).len][]const u8 {
552 comptime {
552 return comptime blk: {
553553 const fieldInfos = fields(T);
554554 var names: [fieldInfos.len][]const u8 = undefined;
555555 for (fieldInfos, 0..) |field, i| {
556556 names[i] = field.name;
557557 }
558 return &names;
559 }
558 break :blk &names;
559 };
560560}
561561
562562test "std.meta.fieldNames" {
......@@ -590,14 +590,14 @@ test "std.meta.fieldNames" {
590590/// Given an enum or error set type, returns a pointer to an array containing all tags for that
591591/// enum or error set.
592592pub fn tags(comptime T: type) *const [fields(T).len]T {
593 comptime {
593 return comptime blk: {
594594 const fieldInfos = fields(T);
595595 var res: [fieldInfos.len]T = undefined;
596596 for (fieldInfos, 0..) |field, i| {
597597 res[i] = @field(T, field.name);
598598 }
599 return &res;
600 }
599 break :blk &res;
600 };
601601}
602602
603603test "std.meta.tags" {
lib/std/meta/trait.zig+7-7
......@@ -400,18 +400,18 @@ test "isTuple" {
400400/// *const u8, ?[]const u8, ?*const [N]u8.
401401/// ```
402402pub fn isZigString(comptime T: type) bool {
403 comptime {
403 return comptime blk: {
404404 // Only pointer types can be strings, no optionals
405405 const info = @typeInfo(T);
406 if (info != .Pointer) return false;
406 if (info != .Pointer) break :blk false;
407407
408408 const ptr = &info.Pointer;
409409 // Check for CV qualifiers that would prevent coerction to []const u8
410 if (ptr.is_volatile or ptr.is_allowzero) return false;
410 if (ptr.is_volatile or ptr.is_allowzero) break :blk false;
411411
412412 // If it's already a slice, simple check.
413413 if (ptr.size == .Slice) {
414 return ptr.child == u8;
414 break :blk ptr.child == u8;
415415 }
416416
417417 // Otherwise check if it's an array type that coerces to slice.
......@@ -419,12 +419,12 @@ pub fn isZigString(comptime T: type) bool {
419419 const child = @typeInfo(ptr.child);
420420 if (child == .Array) {
421421 const arr = &child.Array;
422 return arr.child == u8;
422 break :blk arr.child == u8;
423423 }
424424 }
425425
426 return false;
427 }
426 break :blk false;
427 };
428428}
429429
430430test "isZigString" {
lib/std/net/test.zig+1-1
......@@ -99,7 +99,7 @@ test "parse and render UNIX addresses" {
9999 const fmt_addr = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
100100 try std.testing.expectEqualSlices(u8, "/tmp/testpath", fmt_addr);
101101
102 const too_long = [_]u8{'a'} ** (addr.un.path.len + 1);
102 const too_long = [_]u8{'a'} ** 200;
103103 try testing.expectError(error.NameTooLong, net.Address.initUnix(too_long[0..]));
104104}
105105
lib/std/unicode.zig+3-3
......@@ -774,13 +774,13 @@ test "utf8ToUtf16LeWithNull" {
774774
775775/// Converts a UTF-8 string literal into a UTF-16LE string literal.
776776pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8) catch unreachable:0]u16 {
777 comptime {
777 return comptime blk: {
778778 const len: usize = calcUtf16LeLen(utf8) catch |err| @compileError(err);
779779 var utf16le: [len:0]u16 = [_:0]u16{0} ** len;
780780 const utf16le_len = utf8ToUtf16Le(&utf16le, utf8[0..]) catch |err| @compileError(err);
781781 assert(len == utf16le_len);
782 return &utf16le;
783 }
782 break :blk &utf16le;
783 };
784784}
785785
786786const CalcUtf16LeLenError = Utf8DecodeError || error{Utf8InvalidStartByte};
lib/std/zig/system/linux.zig+5-3
......@@ -147,7 +147,9 @@ test "cpuinfo: PowerPC" {
147147}
148148
149149const ArmCpuinfoImpl = struct {
150 cores: [4]CoreInfo = undefined,
150 const num_cores = 4;
151
152 cores: [num_cores]CoreInfo = undefined,
151153 core_no: usize = 0,
152154 have_fields: usize = 0,
153155
......@@ -162,7 +164,7 @@ const ArmCpuinfoImpl = struct {
162164 const cpu_models = @import("arm.zig").cpu_models;
163165
164166 fn addOne(self: *ArmCpuinfoImpl) void {
165 if (self.have_fields == 4 and self.core_no < self.cores.len) {
167 if (self.have_fields == 4 and self.core_no < num_cores) {
166168 if (self.core_no > 0) {
167169 // Deduplicate the core info.
168170 for (self.cores[0..self.core_no]) |it| {
......@@ -222,7 +224,7 @@ const ArmCpuinfoImpl = struct {
222224 else => false,
223225 };
224226
225 var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined;
227 var known_models: [num_cores]?*const Target.Cpu.Model = undefined;
226228 for (self.cores[0..self.core_no], 0..) |core, i| {
227229 known_models[i] = cpu_models.isKnown(.{
228230 .architecture = core.architecture,
src/AstGen.zig+157-119
......@@ -137,7 +137,7 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
137137
138138 var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
139139 var gen_scope: GenZir = .{
140 .force_comptime = true,
140 .is_comptime = true,
141141 .parent = &top_scope.base,
142142 .anon_name_strategy = .parent,
143143 .decl_node_index = 0,
......@@ -362,11 +362,7 @@ const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } };
362362const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };
363363
364364fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
365 const prev_force_comptime = gz.force_comptime;
366 gz.force_comptime = true;
367 defer gz.force_comptime = prev_force_comptime;
368
369 return expr(gz, scope, coerced_type_ri, type_node);
365 return comptimeExpr(gz, scope, coerced_type_ri, type_node);
370366}
371367
372368fn reachableTypeExpr(
......@@ -375,11 +371,7 @@ fn reachableTypeExpr(
375371 type_node: Ast.Node.Index,
376372 reachable_node: Ast.Node.Index,
377373) InnerError!Zir.Inst.Ref {
378 const prev_force_comptime = gz.force_comptime;
379 gz.force_comptime = true;
380 defer gz.force_comptime = prev_force_comptime;
381
382 return reachableExpr(gz, scope, coerced_type_ri, type_node, reachable_node);
374 return reachableExprComptime(gz, scope, coerced_type_ri, type_node, reachable_node, true);
383375}
384376
385377/// Same as `expr` but fails with a compile error if the result type is `noreturn`.
......@@ -401,11 +393,11 @@ fn reachableExprComptime(
401393 reachable_node: Ast.Node.Index,
402394 force_comptime: bool,
403395) InnerError!Zir.Inst.Ref {
404 const prev_force_comptime = gz.force_comptime;
405 gz.force_comptime = prev_force_comptime or force_comptime;
406 defer gz.force_comptime = prev_force_comptime;
396 const result_inst = if (force_comptime)
397 try comptimeExpr(gz, scope, ri, node)
398 else
399 try expr(gz, scope, ri, node);
407400
408 const result_inst = try expr(gz, scope, ri, node);
409401 if (gz.refIsNoReturn(result_inst)) {
410402 try gz.astgen.appendErrorNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{
411403 try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}),
......@@ -825,7 +817,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
825817 _ = try gz.addAsIndex(.{
826818 .tag = .@"unreachable",
827819 .data = .{ .@"unreachable" = .{
828 .force_comptime = gz.force_comptime,
829820 .src_node = gz.nodeIndexToRelative(node),
830821 } },
831822 });
......@@ -1578,12 +1569,7 @@ fn arrayInitExprRlPtrInner(
15781569 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = elem_ptr } } }, elem_init);
15791570 }
15801571
1581 const tag: Zir.Inst.Tag = if (gz.force_comptime)
1582 .validate_array_init_comptime
1583 else
1584 .validate_array_init;
1585
1586 _ = try gz.addPlNodePayloadIndex(tag, node, payload_index);
1572 _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index);
15871573 return .void_value;
15881574}
15891575
......@@ -1800,12 +1786,7 @@ fn structInitExprRlPtrInner(
18001786 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init);
18011787 }
18021788
1803 const tag: Zir.Inst.Tag = if (gz.force_comptime)
1804 .validate_struct_init_comptime
1805 else
1806 .validate_struct_init;
1807
1808 _ = try gz.addPlNodePayloadIndex(tag, node, payload_index);
1789 _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index);
18091790 return Zir.Inst.Ref.void_value;
18101791}
18111792
......@@ -1843,23 +1824,105 @@ fn structInitExprRlTy(
18431824 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
18441825}
18451826
1846/// This calls expr in a comptime scope, and is intended to be called as a helper function.
1847/// The one that corresponds to `comptime` expression syntax is `comptimeExprAst`.
1827/// This explicitly calls expr in a comptime scope by wrapping it in a `block_comptime` if
1828/// necessary. It should be used whenever we need to force compile-time evaluation of something,
1829/// such as a type.
1830/// The function corresponding to `comptime` expression syntax is `comptimeExprAst`.
18481831fn comptimeExpr(
18491832 gz: *GenZir,
18501833 scope: *Scope,
18511834 ri: ResultInfo,
18521835 node: Ast.Node.Index,
18531836) InnerError!Zir.Inst.Ref {
1854 const prev_force_comptime = gz.force_comptime;
1855 gz.force_comptime = true;
1856 defer gz.force_comptime = prev_force_comptime;
1837 if (gz.is_comptime) {
1838 // No need to change anything!
1839 return expr(gz, scope, ri, node);
1840 }
18571841
1858 return expr(gz, scope, ri, node);
1842 // There's an optimization here: if the body will be evaluated at comptime regardless, there's
1843 // no need to wrap it in a block. This is hard to determine in general, but we can identify a
1844 // common subset of trivially comptime expressions to take down the size of the ZIR a bit.
1845 const tree = gz.astgen.tree;
1846 const main_tokens = tree.nodes.items(.main_token);
1847 const node_tags = tree.nodes.items(.tag);
1848 switch (node_tags[node]) {
1849 // Any identifier in `primitive_instrs` is trivially comptime. In particular, this includes
1850 // some common types, so we can elide `block_comptime` for a few common type annotations.
1851 .identifier => {
1852 const ident_token = main_tokens[node];
1853 const ident_name_raw = tree.tokenSlice(ident_token);
1854 if (primitive_instrs.get(ident_name_raw)) |zir_const_ref| {
1855 // No need to worry about result location here, we're not creating a comptime block!
1856 return rvalue(gz, ri, zir_const_ref, node);
1857 }
1858 },
1859
1860 // We can also avoid the block for a few trivial AST tags which are always comptime-known.
1861 .number_literal, .string_literal, .multiline_string_literal, .enum_literal, .error_value => {
1862 // No need to worry about result location here, we're not creating a comptime block!
1863 return expr(gz, scope, ri, node);
1864 },
1865
1866 // Lastly, for labelled blocks, avoid emitting a labelled block directly inside this
1867 // comptime block, because that would be silly! Note that we don't bother doing this for
1868 // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`).
1869 .block_two, .block_two_semicolon, .block, .block_semicolon => {
1870 const token_tags = tree.tokens.items(.tag);
1871 const lbrace = main_tokens[node];
1872 if (token_tags[lbrace - 1] == .colon and
1873 token_tags[lbrace - 2] == .identifier)
1874 {
1875 const node_datas = tree.nodes.items(.data);
1876 switch (node_tags[node]) {
1877 .block_two, .block_two_semicolon => {
1878 const stmts: [2]Ast.Node.Index = .{ node_datas[node].lhs, node_datas[node].rhs };
1879 const stmt_slice = if (stmts[0] == 0)
1880 stmts[0..0]
1881 else if (stmts[1] == 0)
1882 stmts[0..1]
1883 else
1884 stmts[0..2];
1885
1886 // Careful! We can't pass in the real result location here, since it may
1887 // refer to runtime memory. A runtime-to-comptime boundary has to remove
1888 // result location information, compute the result, and copy it to the true
1889 // result location at runtime. We do this below as well.
1890 const block_ref = try labeledBlockExpr(gz, scope, .{ .rl = .none }, node, stmt_slice, true);
1891 return rvalue(gz, ri, block_ref, node);
1892 },
1893 .block, .block_semicolon => {
1894 const stmts = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
1895 // Replace result location and copy back later - see above.
1896 const block_ref = try labeledBlockExpr(gz, scope, .{ .rl = .none }, node, stmts, true);
1897 return rvalue(gz, ri, block_ref, node);
1898 },
1899 else => unreachable,
1900 }
1901 }
1902 },
1903
1904 // In other cases, we don't optimize anything - we need a wrapper comptime block.
1905 else => {},
1906 }
1907
1908 var block_scope = gz.makeSubBlock(scope);
1909 block_scope.is_comptime = true;
1910 defer block_scope.unstack();
1911
1912 const block_inst = try gz.makeBlockInst(.block_comptime, node);
1913 // Replace result location and copy back later - see above.
1914 const block_result = try expr(&block_scope, scope, .{ .rl = .none }, node);
1915 if (!gz.refIsNoReturn(block_result)) {
1916 _ = try block_scope.addBreak(.@"break", block_inst, block_result);
1917 }
1918 try block_scope.setBlockBody(block_inst);
1919 try gz.instructions.append(gz.astgen.gpa, block_inst);
1920
1921 return rvalue(gz, ri, indexToRef(block_inst), node);
18591922}
18601923
18611924/// This one is for an actual `comptime` syntax, and will emit a compile error if
1862/// the scope already has `force_comptime=true`.
1925/// the scope is already known to be comptime-evaluated.
18631926/// See `comptimeExpr` for the helper function for calling expr in a comptime scope.
18641927fn comptimeExprAst(
18651928 gz: *GenZir,
......@@ -1868,16 +1931,13 @@ fn comptimeExprAst(
18681931 node: Ast.Node.Index,
18691932) InnerError!Zir.Inst.Ref {
18701933 const astgen = gz.astgen;
1871 if (gz.force_comptime) {
1934 if (gz.is_comptime) {
18721935 return astgen.failNode(node, "redundant comptime keyword in already comptime scope", .{});
18731936 }
18741937 const tree = astgen.tree;
18751938 const node_datas = tree.nodes.items(.data);
18761939 const body_node = node_datas[node].lhs;
1877 gz.force_comptime = true;
1878 const result = try expr(gz, scope, ri, body_node);
1879 gz.force_comptime = false;
1880 return result;
1940 return comptimeExpr(gz, scope, ri, body_node);
18811941}
18821942
18831943/// Restore the error return trace index. Performs the restore only if the result is a non-error or
......@@ -1961,7 +2021,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
19612021 };
19622022 // If we made it here, this block is the target of the break expr
19632023
1964 const break_tag: Zir.Inst.Tag = if (block_gz.is_inline or block_gz.force_comptime)
2024 const break_tag: Zir.Inst.Tag = if (block_gz.is_inline)
19652025 .break_inline
19662026 else
19672027 .@"break";
......@@ -1973,7 +2033,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
19732033 try genDefers(parent_gz, scope, parent_scope, .normal_only);
19742034
19752035 // As our last action before the break, "pop" the error trace if needed
1976 if (!block_gz.force_comptime)
2036 if (!block_gz.is_comptime)
19772037 _ = try parent_gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
19782038
19792039 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
......@@ -1986,7 +2046,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
19862046 try genDefers(parent_gz, scope, parent_scope, .normal_only);
19872047
19882048 // As our last action before the break, "pop" the error trace if needed
1989 if (!block_gz.force_comptime)
2049 if (!block_gz.is_comptime)
19902050 try restoreErrRetIndex(parent_gz, .{ .block = block_inst }, block_gz.break_result_info, rhs, operand);
19912051
19922052 switch (block_gz.break_result_info.rl) {
......@@ -2062,7 +2122,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
20622122 continue;
20632123 }
20642124
2065 const break_tag: Zir.Inst.Tag = if (gen_zir.is_inline or gen_zir.force_comptime)
2125 const break_tag: Zir.Inst.Tag = if (gen_zir.is_inline)
20662126 .break_inline
20672127 else
20682128 .@"break";
......@@ -2071,7 +2131,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
20712131 }
20722132
20732133 // As our last action before the continue, "pop" the error trace if needed
2074 if (!gen_zir.force_comptime)
2134 if (!gen_zir.is_comptime)
20752135 _ = try parent_gz.addRestoreErrRetIndex(.{ .block = continue_block }, .always);
20762136
20772137 _ = try parent_gz.addBreak(break_tag, continue_block, .void_value);
......@@ -2116,10 +2176,10 @@ fn blockExpr(
21162176 if (token_tags[lbrace - 1] == .colon and
21172177 token_tags[lbrace - 2] == .identifier)
21182178 {
2119 return labeledBlockExpr(gz, scope, ri, block_node, statements);
2179 return labeledBlockExpr(gz, scope, ri, block_node, statements, false);
21202180 }
21212181
2122 if (!gz.force_comptime) {
2182 if (!gz.is_comptime) {
21232183 // Since this block is unlabeled, its control flow is effectively linear and we
21242184 // can *almost* get away with inlining the block here. However, we actually need
21252185 // to preserve the .block for Sema, to properly pop the error return trace.
......@@ -2136,9 +2196,7 @@ fn blockExpr(
21362196 if (!block_scope.endsWithNoReturn()) {
21372197 // As our last action before the break, "pop" the error trace if needed
21382198 _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
2139
2140 const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break";
2141 _ = try block_scope.addBreak(break_tag, block_inst, .void_value);
2199 _ = try block_scope.addBreak(.@"break", block_inst, .void_value);
21422200 }
21432201
21442202 try block_scope.setBlockBody(block_inst);
......@@ -2188,6 +2246,7 @@ fn labeledBlockExpr(
21882246 ri: ResultInfo,
21892247 block_node: Ast.Node.Index,
21902248 statements: []const Ast.Node.Index,
2249 force_comptime: bool,
21912250) InnerError!Zir.Inst.Ref {
21922251 const tracy = trace(@src());
21932252 defer tracy.end();
......@@ -2205,16 +2264,16 @@ fn labeledBlockExpr(
22052264
22062265 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
22072266 // so that break statements can reference it.
2208 const block_tag: Zir.Inst.Tag = if (gz.force_comptime) .block_inline else .block;
2267 const block_tag: Zir.Inst.Tag = if (force_comptime) .block_comptime else .block;
22092268 const block_inst = try gz.makeBlockInst(block_tag, block_node);
22102269 try gz.instructions.append(astgen.gpa, block_inst);
2211
22122270 var block_scope = gz.makeSubBlock(parent_scope);
22132271 block_scope.label = GenZir.Label{
22142272 .token = label_token,
22152273 .block_inst = block_inst,
22162274 };
22172275 block_scope.setBreakResultInfo(ri);
2276 if (force_comptime) block_scope.is_comptime = true;
22182277 defer block_scope.unstack();
22192278 defer block_scope.labeled_breaks.deinit(astgen.gpa);
22202279
......@@ -2222,9 +2281,7 @@ fn labeledBlockExpr(
22222281 if (!block_scope.endsWithNoReturn()) {
22232282 // As our last action before the return, "pop" the error trace if needed
22242283 _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always);
2225
2226 const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break";
2227 _ = try block_scope.addBreak(break_tag, block_inst, .void_value);
2284 _ = try block_scope.addBreak(.@"break", block_inst, .void_value);
22282285 }
22292286
22302287 if (!block_scope.label.?.used) {
......@@ -2436,6 +2493,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
24362493 .bitcast,
24372494 .bit_or,
24382495 .block,
2496 .block_comptime,
24392497 .block_inline,
24402498 .suspend_block,
24412499 .loop,
......@@ -2610,8 +2668,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
26102668 .for_len,
26112669 .@"try",
26122670 .try_ptr,
2613 //.try_inline,
2614 //.try_ptr_inline,
26152671 => break :b false,
26162672
26172673 .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {
......@@ -2638,7 +2694,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
26382694 .repeat,
26392695 .repeat_inline,
26402696 .panic,
2641 .panic_comptime,
26422697 .trap,
26432698 .check_comptime_control_flow,
26442699 => {
......@@ -2665,9 +2720,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
26652720 .store_to_inferred_ptr,
26662721 .resolve_inferred_alloc,
26672722 .validate_struct_init,
2668 .validate_struct_init_comptime,
26692723 .validate_array_init,
2670 .validate_array_init_comptime,
26712724 .set_runtime_safety,
26722725 .closure_capture,
26732726 .memcpy,
......@@ -2988,7 +3041,7 @@ fn varDecl(
29883041 return &sub_scope.base;
29893042 }
29903043
2991 const is_comptime = gz.force_comptime or
3044 const is_comptime = gz.is_comptime or
29923045 tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";
29933046
29943047 // Detect whether the initialization expression actually uses the
......@@ -3133,7 +3186,7 @@ fn varDecl(
31333186 const old_rl_ty_inst = gz.rl_ty_inst;
31343187 defer gz.rl_ty_inst = old_rl_ty_inst;
31353188
3136 const is_comptime = var_decl.comptime_token != null or gz.force_comptime;
3189 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;
31373190 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
31383191 const var_data: struct {
31393192 result_info: ResultInfo,
......@@ -3211,7 +3264,7 @@ fn emitDbgNode(gz: *GenZir, node: Ast.Node.Index) !void {
32113264 // The instruction emitted here is for debugging runtime code.
32123265 // If the current block will be evaluated only during semantic analysis
32133266 // then no dbg_stmt ZIR instruction is needed.
3214 if (gz.force_comptime) return;
3267 if (gz.is_comptime) return;
32153268
32163269 const astgen = gz.astgen;
32173270 astgen.advanceSourceCursorToNode(node);
......@@ -3631,7 +3684,7 @@ fn fnDecl(
36313684 astgen.advanceSourceCursorToNode(decl_node);
36323685
36333686 var decl_gz: GenZir = .{
3634 .force_comptime = true,
3687 .is_comptime = true,
36353688 .decl_node_index = fn_proto.ast.proto_node,
36363689 .decl_line = astgen.source_line,
36373690 .parent = scope,
......@@ -3642,7 +3695,7 @@ fn fnDecl(
36423695 defer decl_gz.unstack();
36433696
36443697 var fn_gz: GenZir = .{
3645 .force_comptime = false,
3698 .is_comptime = false,
36463699 .decl_node_index = fn_proto.ast.proto_node,
36473700 .decl_line = decl_gz.decl_line,
36483701 .parent = &decl_gz.base,
......@@ -4005,7 +4058,7 @@ fn globalVarDecl(
40054058 .decl_node_index = node,
40064059 .decl_line = astgen.source_line,
40074060 .astgen = astgen,
4008 .force_comptime = true,
4061 .is_comptime = true,
40094062 .anon_name_strategy = .parent,
40104063 .instructions = gz.instructions,
40114064 .instructions_top = gz.instructions.items.len,
......@@ -4156,7 +4209,7 @@ fn comptimeDecl(
41564209 astgen.advanceSourceCursorToNode(node);
41574210
41584211 var decl_block: GenZir = .{
4159 .force_comptime = true,
4212 .is_comptime = true,
41604213 .decl_node_index = node,
41614214 .decl_line = astgen.source_line,
41624215 .parent = scope,
......@@ -4210,7 +4263,7 @@ fn usingnamespaceDecl(
42104263 astgen.advanceSourceCursorToNode(node);
42114264
42124265 var decl_block: GenZir = .{
4213 .force_comptime = true,
4266 .is_comptime = true,
42144267 .decl_node_index = node,
42154268 .decl_line = astgen.source_line,
42164269 .parent = scope,
......@@ -4257,7 +4310,7 @@ fn testDecl(
42574310 astgen.advanceSourceCursorToNode(node);
42584311
42594312 var decl_block: GenZir = .{
4260 .force_comptime = true,
4313 .is_comptime = true,
42614314 .decl_node_index = node,
42624315 .decl_line = astgen.source_line,
42634316 .parent = scope,
......@@ -4353,7 +4406,7 @@ fn testDecl(
43534406 };
43544407
43554408 var fn_block: GenZir = .{
4356 .force_comptime = false,
4409 .is_comptime = false,
43574410 .decl_node_index = node,
43584411 .decl_line = decl_block.decl_line,
43594412 .parent = &decl_block.base,
......@@ -4477,7 +4530,7 @@ fn structDeclInner(
44774530 .decl_node_index = node,
44784531 .decl_line = gz.decl_line,
44794532 .astgen = astgen,
4480 .force_comptime = true,
4533 .is_comptime = true,
44814534 .instructions = gz.instructions,
44824535 .instructions_top = gz.instructions.items.len,
44834536 };
......@@ -4720,7 +4773,7 @@ fn unionDeclInner(
47204773 .decl_node_index = node,
47214774 .decl_line = gz.decl_line,
47224775 .astgen = astgen,
4723 .force_comptime = true,
4776 .is_comptime = true,
47244777 .instructions = gz.instructions,
47254778 .instructions_top = gz.instructions.items.len,
47264779 };
......@@ -5006,7 +5059,7 @@ fn containerDecl(
50065059 .decl_node_index = node,
50075060 .decl_line = gz.decl_line,
50085061 .astgen = astgen,
5009 .force_comptime = true,
5062 .is_comptime = true,
50105063 .instructions = gz.instructions,
50115064 .instructions_top = gz.instructions.items.len,
50125065 };
......@@ -5115,7 +5168,7 @@ fn containerDecl(
51155168 .decl_node_index = node,
51165169 .decl_line = gz.decl_line,
51175170 .astgen = astgen,
5118 .force_comptime = true,
5171 .is_comptime = true,
51195172 .instructions = gz.instructions,
51205173 .instructions_top = gz.instructions.items.len,
51215174 };
......@@ -5304,7 +5357,7 @@ fn tryExpr(
53045357 // Then we will save the line/column so that we can emit another one that goes
53055358 // "backwards" because we want to evaluate the operand, but then put the debug
53065359 // info back at the try keyword for error return tracing.
5307 if (!parent_gz.force_comptime) {
5360 if (!parent_gz.is_comptime) {
53085361 try emitDbgNode(parent_gz, node);
53095362 }
53105363 const try_line = astgen.source_line - parent_gz.decl_line;
......@@ -5316,17 +5369,7 @@ fn tryExpr(
53165369 };
53175370 // This could be a pointer or value depending on the `ri` parameter.
53185371 const operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node);
5319 const is_inline = parent_gz.force_comptime;
5320 const is_inline_bit = @as(u2, @boolToInt(is_inline));
5321 const is_ptr_bit = @as(u2, @boolToInt(operand_ri.rl == .ref)) << 1;
5322 const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) {
5323 0b00 => .@"try",
5324 0b01 => .@"try",
5325 //0b01 => .try_inline,
5326 0b10 => .try_ptr,
5327 0b11 => .try_ptr,
5328 //0b11 => .try_ptr_inline,
5329 };
5372 const block_tag: Zir.Inst.Tag = if (operand_ri.rl == .ref) .try_ptr else .@"try";
53305373 const try_inst = try parent_gz.makeBlockInst(block_tag, node);
53315374 try parent_gz.instructions.append(astgen.gpa, try_inst);
53325375
......@@ -5382,11 +5425,9 @@ fn orelseCatchExpr(
53825425 // up for this fact by calling rvalue on the else branch.
53835426 const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs);
53845427 const cond = try block_scope.addUnNode(cond_op, operand, node);
5385 const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr;
5386 const condbr = try block_scope.addCondBr(condbr_tag, node);
5428 const condbr = try block_scope.addCondBr(.condbr, node);
53875429
5388 const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block;
5389 const block = try parent_gz.makeBlockInst(block_tag, node);
5430 const block = try parent_gz.makeBlockInst(.block, node);
53905431 try block_scope.setBlockBody(block);
53915432 // block_scope unstacked now, can add new instructions to parent_gz
53925433 try parent_gz.instructions.append(astgen.gpa, block);
......@@ -5445,7 +5486,6 @@ fn orelseCatchExpr(
54455486 // instructions into place until we know whether to keep store_to_block_ptr
54465487 // instructions or not.
54475488
5448 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
54495489 const result = try finishThenElseBlock(
54505490 parent_gz,
54515491 ri,
......@@ -5461,7 +5501,7 @@ fn orelseCatchExpr(
54615501 rhs,
54625502 block,
54635503 block,
5464 break_tag,
5504 .@"break",
54655505 );
54665506 return result;
54675507}
......@@ -5747,11 +5787,9 @@ fn ifExpr(
57475787 }
57485788 };
57495789
5750 const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr;
5751 const condbr = try block_scope.addCondBr(condbr_tag, node);
5790 const condbr = try block_scope.addCondBr(.condbr, node);
57525791
5753 const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block;
5754 const block = try parent_gz.makeBlockInst(block_tag, node);
5792 const block = try parent_gz.makeBlockInst(.block, node);
57555793 try block_scope.setBlockBody(block);
57565794 // block_scope unstacked now, can add new instructions to parent_gz
57575795 try parent_gz.instructions.append(astgen.gpa, block);
......@@ -5891,7 +5929,6 @@ fn ifExpr(
58915929 },
58925930 };
58935931
5894 const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
58955932 const result = try finishThenElseBlock(
58965933 parent_gz,
58975934 ri,
......@@ -5907,7 +5944,7 @@ fn ifExpr(
59075944 else_info.src,
59085945 block,
59095946 block,
5910 break_tag,
5947 .@"break",
59115948 );
59125949 return result;
59135950}
......@@ -6043,7 +6080,7 @@ fn whileExpr(
60436080 try astgen.checkLabelRedefinition(scope, label_token);
60446081 }
60456082
6046 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;
6083 const is_inline = while_full.inline_token != null;
60476084 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;
60486085 const loop_block = try parent_gz.makeBlockInst(loop_tag, node);
60496086 try parent_gz.instructions.append(astgen.gpa, loop_block);
......@@ -6315,7 +6352,7 @@ fn forExpr(
63156352 try astgen.checkLabelRedefinition(scope, label_token);
63166353 }
63176354
6318 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
6355 const is_inline = for_full.inline_token != null;
63196356 const tree = astgen.tree;
63206357 const token_tags = tree.tokens.items(.tag);
63216358 const node_tags = tree.nodes.items(.tag);
......@@ -7114,7 +7151,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
71147151 // Then we will save the line/column so that we can emit another one that goes
71157152 // "backwards" because we want to evaluate the operand, but then put the debug
71167153 // info back at the return keyword for error return tracing.
7117 if (!gz.force_comptime) {
7154 if (!gz.is_comptime) {
71187155 try emitDbgNode(gz, node);
71197156 }
71207157 const ret_line = astgen.source_line - gz.decl_line;
......@@ -7859,7 +7896,7 @@ fn typeOf(
78597896 const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node);
78607897
78617898 var typeof_scope = gz.makeSubBlock(scope);
7862 typeof_scope.force_comptime = false;
7899 typeof_scope.is_comptime = false;
78637900 typeof_scope.c_import = false;
78647901 defer typeof_scope.unstack();
78657902
......@@ -7880,7 +7917,7 @@ fn typeOf(
78807917 const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len);
78817918
78827919 var typeof_scope = gz.makeSubBlock(scope);
7883 typeof_scope.force_comptime = false;
7920 typeof_scope.is_comptime = false;
78847921
78857922 for (args, 0..) |arg, i| {
78867923 const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, arg, node);
......@@ -8207,7 +8244,7 @@ fn builtinCall(
82078244 },
82088245 .panic => {
82098246 try emitDbgNode(gz, node);
8210 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], if (gz.force_comptime) .panic_comptime else .panic);
8247 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .panic);
82118248 },
82128249 .trap => {
82138250 try emitDbgNode(gz, node);
......@@ -8431,7 +8468,6 @@ fn builtinCall(
84318468 .args = args,
84328469 .flags = .{
84338470 .is_nosuspend = gz.nosuspend_node != 0,
8434 .is_comptime = gz.force_comptime,
84358471 .ensure_result_used = false,
84368472 },
84378473 });
......@@ -8644,15 +8680,14 @@ fn simpleUnOp(
86448680 operand_node: Ast.Node.Index,
86458681 tag: Zir.Inst.Tag,
86468682) InnerError!Zir.Inst.Ref {
8647 const prev_force_comptime = gz.force_comptime;
8648 defer gz.force_comptime = prev_force_comptime;
8649
86508683 switch (tag) {
86518684 .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node),
8652 .compile_error => gz.force_comptime = true,
86538685 else => {},
86548686 }
8655 const operand = try expr(gz, scope, operand_ri, operand_node);
8687 const operand = if (tag == .compile_error)
8688 try comptimeExpr(gz, scope, operand_ri, operand_node)
8689 else
8690 try expr(gz, scope, operand_ri, operand_node);
86568691 const result = try gz.addUnNode(tag, operand, node);
86578692 return rvalue(gz, ri, result, node);
86588693}
......@@ -8814,7 +8849,7 @@ fn cImport(
88148849 if (gz.c_import) return gz.astgen.failNode(node, "cannot nest @cImport", .{});
88158850
88168851 var block_scope = gz.makeSubBlock(scope);
8817 block_scope.force_comptime = true;
8852 block_scope.is_comptime = true;
88188853 block_scope.c_import = true;
88198854 defer block_scope.unstack();
88208855
......@@ -8860,7 +8895,7 @@ fn callExpr(
88608895
88618896 const callee = try calleeExpr(gz, scope, call.ast.fn_expr);
88628897 const modifier: std.builtin.CallModifier = blk: {
8863 if (gz.force_comptime) {
8898 if (gz.is_comptime) {
88648899 break :blk .compile_time;
88658900 }
88668901 if (call.async_token != null) {
......@@ -10875,7 +10910,10 @@ const Scope = struct {
1087510910const GenZir = struct {
1087610911 const base_tag: Scope.Tag = .gen_zir;
1087710912 base: Scope = Scope{ .tag = base_tag },
10878 force_comptime: bool,
10913 /// Whether we're already in a scope known to be comptime. This is set
10914 /// whenever we know Sema will analyze the current block with `is_comptime`,
10915 /// for instance when we're within a `struct_decl` or a `block_comptime`.
10916 is_comptime: bool,
1087910917 /// This is set to true for inline loops; false otherwise.
1088010918 is_inline: bool = false,
1088110919 c_import: bool = false,
......@@ -10962,7 +11000,7 @@ const GenZir = struct {
1096211000
1096311001 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
1096411002 return .{
10965 .force_comptime = gz.force_comptime,
11003 .is_comptime = gz.is_comptime,
1096611004 .c_import = gz.c_import,
1096711005 .decl_node_index = gz.decl_node_index,
1096811006 .decl_line = gz.decl_line,
......@@ -12405,7 +12443,7 @@ const GenZir = struct {
1240512443 }
1240612444
1240712445 fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: u32, inst: Zir.Inst.Ref) !void {
12408 if (gz.force_comptime) return;
12446 if (gz.is_comptime) return;
1240912447
1241012448 _ = try gz.add(.{ .tag = tag, .data = .{
1241112449 .str_op = .{
......@@ -12416,13 +12454,13 @@ const GenZir = struct {
1241612454 }
1241712455
1241812456 fn addDbgBlockBegin(gz: *GenZir) !void {
12419 if (gz.force_comptime) return;
12457 if (gz.is_comptime) return;
1242012458
1242112459 _ = try gz.add(.{ .tag = .dbg_block_begin, .data = undefined });
1242212460 }
1242312461
1242412462 fn addDbgBlockEnd(gz: *GenZir) !void {
12425 if (gz.force_comptime) return;
12463 if (gz.is_comptime) return;
1242612464 const gpa = gz.astgen.gpa;
1242712465
1242812466 const tags = gz.astgen.instructions.items(.tag);
......@@ -12554,7 +12592,7 @@ fn detectLocalShadowing(
1255412592/// Advances the source cursor to the main token of `node` if not in comptime scope.
1255512593/// Usually paired with `emitDbgStmt`.
1255612594fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) void {
12557 if (gz.force_comptime) return;
12595 if (gz.is_comptime) return;
1255812596
1255912597 const tree = gz.astgen.tree;
1256012598 const token_starts = tree.tokens.items(.start);
......@@ -12765,7 +12803,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
1276512803}
1276612804
1276712805fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
12768 if (gz.force_comptime) return;
12806 if (gz.is_comptime) return;
1276912807
1277012808 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
1277112809 .dbg_stmt = .{
src/Sema.zig+23-89
......@@ -1112,8 +1112,7 @@ fn analyzeBodyInner(
11121112 .ret_load => break sema.zirRetLoad(block, inst),
11131113 .ret_err_value => break sema.zirRetErrValue(block, inst),
11141114 .@"unreachable" => break sema.zirUnreachable(block, inst),
1115 .panic => break sema.zirPanic(block, inst, false),
1116 .panic_comptime => break sema.zirPanic(block, inst, true),
1115 .panic => break sema.zirPanic(block, inst),
11171116 .trap => break sema.zirTrap(block, inst),
11181117 // zig fmt: on
11191118
......@@ -1292,22 +1291,12 @@ fn analyzeBodyInner(
12921291 continue;
12931292 },
12941293 .validate_struct_init => {
1295 try sema.zirValidateStructInit(block, inst, false);
1296 i += 1;
1297 continue;
1298 },
1299 .validate_struct_init_comptime => {
1300 try sema.zirValidateStructInit(block, inst, true);
1294 try sema.zirValidateStructInit(block, inst);
13011295 i += 1;
13021296 continue;
13031297 },
13041298 .validate_array_init => {
1305 try sema.zirValidateArrayInit(block, inst, false);
1306 i += 1;
1307 continue;
1308 },
1309 .validate_array_init_comptime => {
1310 try sema.zirValidateArrayInit(block, inst, true);
1299 try sema.zirValidateArrayInit(block, inst);
13111300 i += 1;
13121301 continue;
13131302 },
......@@ -1464,8 +1453,10 @@ fn analyzeBodyInner(
14641453 break break_data.inst;
14651454 }
14661455 },
1467 .block => blk: {
1468 if (!block.is_comptime) break :blk try sema.zirBlock(block, inst);
1456 .block, .block_comptime => blk: {
1457 if (!block.is_comptime) {
1458 break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
1459 }
14691460 // Same as `block_inline`. TODO https://github.com/ziglang/zig/issues/8220
14701461 const inst_data = datas[inst].pl_node;
14711462 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
......@@ -1649,38 +1640,6 @@ fn analyzeBodyInner(
16491640 break break_data.inst;
16501641 }
16511642 },
1652 //.try_inline => blk: {
1653 // const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1654 // const src = inst_data.src();
1655 // const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1656 // const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1657 // const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1658 // const operand = try sema.resolveInst(extra.data.operand);
1659 // const operand_ty = sema.typeOf(operand);
1660 // const is_ptr = operand_ty.zigTypeTag() == .Pointer;
1661 // const err_union = if (is_ptr)
1662 // try sema.analyzeLoad(block, src, operand, operand_src)
1663 // else
1664 // operand;
1665 // const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
1666 // assert(is_non_err != .none);
1667 // const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
1668 // if (is_non_err_tv.val.toBool()) {
1669 // if (is_ptr) {
1670 // break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1671 // } else {
1672 // const err_union_ty = sema.typeOf(err_union);
1673 // break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
1674 // }
1675 // }
1676 // const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1677 // break always_noreturn;
1678 // if (inst == break_data.block_inst) {
1679 // break :blk try sema.resolveInst(break_data.operand);
1680 // } else {
1681 // break break_data.inst;
1682 // }
1683 //},
16841643 .try_ptr => blk: {
16851644 if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst);
16861645 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
......@@ -1707,28 +1666,6 @@ fn analyzeBodyInner(
17071666 break break_data.inst;
17081667 }
17091668 },
1710 //.try_ptr_inline => blk: {
1711 // const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1712 // const src = inst_data.src();
1713 // const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1714 // const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1715 // const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1716 // const operand = try sema.resolveInst(extra.data.operand);
1717 // const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
1718 // const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
1719 // assert(is_non_err != .none);
1720 // const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
1721 // if (is_non_err_tv.val.toBool()) {
1722 // break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1723 // }
1724 // const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1725 // break always_noreturn;
1726 // if (inst == break_data.block_inst) {
1727 // break :blk try sema.resolveInst(break_data.operand);
1728 // } else {
1729 // break break_data.inst;
1730 // }
1731 //},
17321669 .@"defer" => blk: {
17331670 const inst_data = sema.code.instructions.items(.data)[inst].@"defer";
17341671 const defer_body = sema.code.extra[inst_data.index..][0..inst_data.len];
......@@ -4175,7 +4112,6 @@ fn zirValidateStructInit(
41754112 sema: *Sema,
41764113 block: *Block,
41774114 inst: Zir.Inst.Index,
4178 is_comptime: bool,
41794115) CompileError!void {
41804116 const tracy = trace(@src());
41814117 defer tracy.end();
......@@ -4194,7 +4130,6 @@ fn zirValidateStructInit(
41944130 agg_ty,
41954131 init_src,
41964132 instrs,
4197 is_comptime,
41984133 ),
41994134 .Union => return sema.validateUnionInit(
42004135 block,
......@@ -4202,7 +4137,6 @@ fn zirValidateStructInit(
42024137 init_src,
42034138 instrs,
42044139 object_ptr,
4205 is_comptime,
42064140 ),
42074141 else => unreachable,
42084142 }
......@@ -4215,7 +4149,6 @@ fn validateUnionInit(
42154149 init_src: LazySrcLoc,
42164150 instrs: []const Zir.Inst.Index,
42174151 union_ptr: Air.Inst.Ref,
4218 is_comptime: bool,
42194152) CompileError!void {
42204153 if (instrs.len != 1) {
42214154 const msg = msg: {
......@@ -4238,7 +4171,7 @@ fn validateUnionInit(
42384171 return sema.failWithOwnedErrorMsg(msg);
42394172 }
42404173
4241 if ((is_comptime or block.is_comptime) and
4174 if (block.is_comptime and
42424175 (try sema.resolveDefinedValue(block, init_src, union_ptr)) != null)
42434176 {
42444177 // In this case, comptime machinery already did everything. No work to do here.
......@@ -4342,7 +4275,6 @@ fn validateStructInit(
43424275 struct_ty: Type,
43434276 init_src: LazySrcLoc,
43444277 instrs: []const Zir.Inst.Index,
4345 is_comptime: bool,
43464278) CompileError!void {
43474279 const gpa = sema.gpa;
43484280
......@@ -4382,7 +4314,7 @@ fn validateStructInit(
43824314 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
43834315
43844316 const struct_ptr = try sema.resolveInst(struct_ptr_zir_ref);
4385 if ((is_comptime or block.is_comptime) and
4317 if (block.is_comptime and
43864318 (try sema.resolveDefinedValue(block, init_src, struct_ptr)) != null)
43874319 {
43884320 try sema.resolveStructLayout(struct_ty);
......@@ -4606,7 +4538,6 @@ fn zirValidateArrayInit(
46064538 sema: *Sema,
46074539 block: *Block,
46084540 inst: Zir.Inst.Index,
4609 is_comptime: bool,
46104541) CompileError!void {
46114542 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
46124543 const init_src = validate_inst.src();
......@@ -4654,7 +4585,7 @@ fn zirValidateArrayInit(
46544585 else => unreachable,
46554586 };
46564587
4657 if ((is_comptime or block.is_comptime) and
4588 if (block.is_comptime and
46584589 (try sema.resolveDefinedValue(block, init_src, array_ptr)) != null)
46594590 {
46604591 // In this case the comptime machinery will have evaluated the store instructions
......@@ -5222,12 +5153,12 @@ fn zirCompileLog(
52225153 return Air.Inst.Ref.void_value;
52235154}
52245155
5225fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bool) CompileError!Zir.Inst.Index {
5156fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
52265157 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
52275158 const src = inst_data.src();
52285159 const msg_inst = try sema.resolveInst(inst_data.operand);
52295160
5230 if (block.is_comptime or force_comptime) {
5161 if (block.is_comptime) {
52315162 return sema.fail(block, src, "encountered @panic at comptime", .{});
52325163 }
52335164 try sema.panicWithMsg(block, src, msg_inst);
......@@ -5441,7 +5372,7 @@ fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) Comp
54415372 return sema.failWithUseOfAsync(parent_block, src);
54425373}
54435374
5444fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5375fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_comptime: bool) CompileError!Air.Inst.Ref {
54455376 const tracy = trace(@src());
54465377 defer tracy.end();
54475378
......@@ -5479,7 +5410,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
54795410 .instructions = .{},
54805411 .label = &label,
54815412 .inlining = parent_block.inlining,
5482 .is_comptime = parent_block.is_comptime,
5413 .is_comptime = parent_block.is_comptime or force_comptime,
54835414 .comptime_reason = parent_block.comptime_reason,
54845415 .is_typeof = parent_block.is_typeof,
54855416 .want_safety = parent_block.want_safety,
......@@ -17140,7 +17071,7 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1714017071 const inst_data = sema.code.instructions.items(.data)[inst].@"unreachable";
1714117072 const src = inst_data.src();
1714217073
17143 if (block.is_comptime or inst_data.force_comptime) {
17074 if (block.is_comptime) {
1714417075 return sema.fail(block, src, "reached unreachable code", .{});
1714517076 }
1714617077 // TODO Add compile error for @optimizeFor occurring too late in a scope.
......@@ -17410,6 +17341,8 @@ fn analyzeRet(
1741017341 try inlining.merges.results.append(sema.gpa, operand);
1741117342 _ = try block.addBr(inlining.merges.block_inst, operand);
1741217343 return always_noreturn;
17344 } else if (block.is_comptime) {
17345 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});
1741317346 }
1741417347
1741517348 try sema.resolveTypeLayout(sema.fn_ret_ty);
......@@ -17422,6 +17355,7 @@ fn analyzeRet(
1742217355 }
1742317356
1742417357 _ = try block.addUnOp(.ret, operand);
17358
1742517359 return always_noreturn;
1742617360}
1742717361
......@@ -21560,7 +21494,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2156021494 switch (modifier) {
2156121495 // These can be upgraded to comptime or nosuspend calls.
2156221496 .auto, .never_tail, .no_async => {
21563 if (extra.flags.is_comptime) {
21497 if (block.is_comptime) {
2156421498 if (modifier == .never_tail) {
2156521499 return sema.fail(block, modifier_src, "unable to perform 'never_tail' call at compile-time", .{});
2156621500 }
......@@ -21575,12 +21509,12 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2157521509 return sema.fail(block, func_src, "modifier '{s}' requires a comptime-known function", .{@tagName(modifier)});
2157621510 };
2157721511
21578 if (extra.flags.is_comptime) {
21512 if (block.is_comptime) {
2157921513 modifier = .compile_time;
2158021514 }
2158121515 },
2158221516 .always_tail => {
21583 if (extra.flags.is_comptime) {
21517 if (block.is_comptime) {
2158421518 modifier = .compile_time;
2158521519 }
2158621520 },
......@@ -21588,12 +21522,12 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2158821522 if (extra.flags.is_nosuspend) {
2158921523 return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{});
2159021524 }
21591 if (extra.flags.is_comptime) {
21525 if (block.is_comptime) {
2159221526 return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{});
2159321527 }
2159421528 },
2159521529 .never_inline => {
21596 if (extra.flags.is_comptime) {
21530 if (block.is_comptime) {
2159721531 return sema.fail(block, modifier_src, "unable to perform 'never_inline' call at compile-time", .{});
2159821532 }
2159921533 },
src/Zir.zig+11-34
......@@ -258,6 +258,9 @@ pub const Inst = struct {
258258 /// A labeled block of code, which can return a value.
259259 /// Uses the `pl_node` union field. Payload is `Block`.
260260 block,
261 /// Like `block`, but forces full evaluation of its contents at compile-time.
262 /// Uses the `pl_node` union field. Payload is `Block`.
263 block_comptime,
261264 /// A list of instructions which are analyzed in the parent context, without
262265 /// generating a runtime block. Must terminate with an "inline" variant of
263266 /// a noreturn instruction.
......@@ -338,14 +341,8 @@ pub const Inst = struct {
338341 /// payload value, as if `err_union_payload_unsafe` was executed on the operand.
339342 /// Uses the `pl_node` union field. Payload is `Try`.
340343 @"try",
341 ///// Same as `try` except the operand is coerced to a comptime value, and
342 ///// only the taken branch is analyzed. The block must terminate with an "inline"
343 ///// variant of a noreturn instruction.
344 //try_inline,
345344 /// Same as `try` except the operand is a pointer and the result is a pointer.
346345 try_ptr,
347 ///// Same as `try_inline` except the operand is a pointer and the result is a pointer.
348 //try_ptr_inline,
349346 /// An error set type definition. Contains a list of field names.
350347 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
351348 error_set_decl,
......@@ -723,9 +720,6 @@ pub const Inst = struct {
723720 /// because it must use one of them to find out the struct type.
724721 /// Uses the `pl_node` field. Payload is `Block`.
725722 validate_struct_init,
726 /// Same as `validate_struct_init` but additionally communicates that the
727 /// resulting struct initialization value is within a comptime scope.
728 validate_struct_init_comptime,
729723 /// Given a set of `elem_ptr_imm` instructions, assumes they are all part of an
730724 /// array initialization expression, and emits a compile error if the number of
731725 /// elements does not match the array type.
......@@ -733,9 +727,6 @@ pub const Inst = struct {
733727 /// because it must use one of them to find out the array type.
734728 /// Uses the `pl_node` field. Payload is `Block`.
735729 validate_array_init,
736 /// Same as `validate_array_init` but additionally communicates that the
737 /// resulting array initialization value is within a comptime scope.
738 validate_array_init_comptime,
739730 /// Check that operand type supports the dereference operand (.*).
740731 /// Uses the `un_node` field.
741732 validate_deref,
......@@ -806,8 +797,6 @@ pub const Inst = struct {
806797 error_name,
807798 /// Implement builtin `@panic`. Uses `un_node`.
808799 panic,
809 /// Same as `panic` but forces comptime.
810 panic_comptime,
811800 /// Implements `@trap`.
812801 /// Uses the `node` field.
813802 trap,
......@@ -1050,6 +1039,7 @@ pub const Inst = struct {
10501039 .bitcast,
10511040 .bit_or,
10521041 .block,
1042 .block_comptime,
10531043 .block_inline,
10541044 .suspend_block,
10551045 .loop,
......@@ -1162,9 +1152,7 @@ pub const Inst = struct {
11621152 .validate_array_init_ty,
11631153 .validate_struct_init_ty,
11641154 .validate_struct_init,
1165 .validate_struct_init_comptime,
11661155 .validate_array_init,
1167 .validate_array_init_comptime,
11681156 .validate_deref,
11691157 .struct_init_empty,
11701158 .struct_init,
......@@ -1254,8 +1242,6 @@ pub const Inst = struct {
12541242 .ret_type,
12551243 .@"try",
12561244 .try_ptr,
1257 //.try_inline,
1258 //.try_ptr_inline,
12591245 .@"defer",
12601246 .defer_err_code,
12611247 .save_err_ret_index,
......@@ -1276,7 +1262,6 @@ pub const Inst = struct {
12761262 .repeat,
12771263 .repeat_inline,
12781264 .panic,
1279 .panic_comptime,
12801265 .trap,
12811266 .check_comptime_control_flow,
12821267 => true,
......@@ -1318,9 +1303,7 @@ pub const Inst = struct {
13181303 .validate_array_init_ty,
13191304 .validate_struct_init_ty,
13201305 .validate_struct_init,
1321 .validate_struct_init_comptime,
13221306 .validate_array_init,
1323 .validate_array_init_comptime,
13241307 .validate_deref,
13251308 .@"export",
13261309 .export_value,
......@@ -1365,6 +1348,7 @@ pub const Inst = struct {
13651348 .bitcast,
13661349 .bit_or,
13671350 .block,
1351 .block_comptime,
13681352 .block_inline,
13691353 .suspend_block,
13701354 .loop,
......@@ -1552,13 +1536,10 @@ pub const Inst = struct {
15521536 .repeat,
15531537 .repeat_inline,
15541538 .panic,
1555 .panic_comptime,
15561539 .trap,
15571540 .for_len,
15581541 .@"try",
15591542 .try_ptr,
1560 //.try_inline,
1561 //.try_ptr_inline,
15621543 => false,
15631544
15641545 .extended => switch (data.extended.opcode) {
......@@ -1603,6 +1584,7 @@ pub const Inst = struct {
16031584 .bit_not = .un_node,
16041585 .bit_or = .pl_node,
16051586 .block = .pl_node,
1587 .block_comptime = .pl_node,
16061588 .block_inline = .pl_node,
16071589 .suspend_block = .pl_node,
16081590 .bool_not = .un_node,
......@@ -1624,8 +1606,6 @@ pub const Inst = struct {
16241606 .condbr_inline = .pl_node,
16251607 .@"try" = .pl_node,
16261608 .try_ptr = .pl_node,
1627 //.try_inline = .pl_node,
1628 //.try_ptr_inline = .pl_node,
16291609 .error_set_decl = .pl_node,
16301610 .error_set_decl_anon = .pl_node,
16311611 .error_set_decl_func = .pl_node,
......@@ -1721,9 +1701,7 @@ pub const Inst = struct {
17211701 .validate_array_init_ty = .pl_node,
17221702 .validate_struct_init_ty = .un_node,
17231703 .validate_struct_init = .pl_node,
1724 .validate_struct_init_comptime = .pl_node,
17251704 .validate_array_init = .pl_node,
1726 .validate_array_init_comptime = .pl_node,
17271705 .validate_deref = .un_node,
17281706 .struct_init_empty = .un_node,
17291707 .field_type = .pl_node,
......@@ -1750,7 +1728,6 @@ pub const Inst = struct {
17501728 .embed_file = .un_node,
17511729 .error_name = .un_node,
17521730 .panic = .un_node,
1753 .panic_comptime = .un_node,
17541731 .trap = .node,
17551732 .set_runtime_safety = .un_node,
17561733 .sqrt = .un_node,
......@@ -2605,7 +2582,6 @@ pub const Inst = struct {
26052582 /// Offset from Decl AST node index.
26062583 /// `Tag` determines which kind of AST node this points to.
26072584 src_node: i32,
2608 force_comptime: bool,
26092585
26102586 pub fn src(self: @This()) LazySrcLoc {
26112587 return LazySrcLoc.nodeOffset(self.src_node);
......@@ -2920,9 +2896,8 @@ pub const Inst = struct {
29202896
29212897 pub const Flags = packed struct {
29222898 is_nosuspend: bool,
2923 is_comptime: bool,
29242899 ensure_result_used: bool,
2925 _: u29 = undefined,
2900 _: u30 = undefined,
29262901
29272902 comptime {
29282903 if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32)
......@@ -3912,7 +3887,7 @@ fn findDeclsInner(
39123887
39133888 // Block instructions, recurse over the bodies.
39143889
3915 .block, .block_inline => {
3890 .block, .block_comptime, .block_inline => {
39163891 const inst_data = datas[inst].pl_node;
39173892 const extra = zir.extraData(Inst.Block, inst_data.payload_index);
39183893 const body = zir.extra[extra.end..][0..extra.data.body_len];
......@@ -4139,7 +4114,9 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
41394114 },
41404115 else => unreachable,
41414116 };
4142 assert(tags[info.param_block] == .block or tags[info.param_block] == .block_inline);
4117 assert(tags[info.param_block] == .block or
4118 tags[info.param_block] == .block_comptime or
4119 tags[info.param_block] == .block_inline);
41434120 const param_block = zir.extraData(Inst.Block, datas[info.param_block].pl_node.payload_index);
41444121 const param_body = zir.extra[param_block.end..][0..param_block.data.body_len];
41454122 var total_params_len: u32 = 0;
src/print_zir.zig+1-4
......@@ -195,7 +195,6 @@ const Writer = struct {
195195 .embed_file,
196196 .error_name,
197197 .panic,
198 .panic_comptime,
199198 .set_runtime_safety,
200199 .sqrt,
201200 .sin,
......@@ -365,13 +364,12 @@ const Writer = struct {
365364 .call => try self.writeCall(stream, inst),
366365
367366 .block,
367 .block_comptime,
368368 .block_inline,
369369 .suspend_block,
370370 .loop,
371371 .validate_struct_init,
372 .validate_struct_init_comptime,
373372 .validate_array_init,
374 .validate_array_init_comptime,
375373 .c_import,
376374 .typeof_builtin,
377375 => try self.writeBlock(stream, inst),
......@@ -811,7 +809,6 @@ const Writer = struct {
811809
812810 try self.writeFlag(stream, "nodiscard ", extra.flags.ensure_result_used);
813811 try self.writeFlag(stream, "nosuspend ", extra.flags.is_nosuspend);
814 try self.writeFlag(stream, "comptime ", extra.flags.is_comptime);
815812
816813 try self.writeInstRef(stream, extra.modifier);
817814 try stream.writeAll(", ");
test/behavior/cast.zig+1-10
......@@ -1455,7 +1455,7 @@ test "floatToInt to zero-bit int" {
14551455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14561456 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14571457
1458 var a: f32 = 0.0;
1458 const a: f32 = 0.0;
14591459 comptime try std.testing.expect(@floatToInt(u0, a) == 0);
14601460}
14611461
......@@ -1507,15 +1507,6 @@ test "optional pointer coerced to optional allowzero pointer" {
15071507 try expect(@ptrToInt(q.?) == 4);
15081508}
15091509
1510test "ptrToInt on const inside comptime block" {
1511 var a = comptime blk: {
1512 const b: u8 = 1;
1513 const c = @ptrToInt(&b);
1514 break :blk c;
1515 };
1516 try expect(@intToPtr(*const u8, a).* == 1);
1517}
1518
15191510test "single item pointer to pointer to array to slice" {
15201511 var x: i32 = 1234;
15211512 try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
test/behavior/eval.zig+1-3
......@@ -181,9 +181,7 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
181181 const result = if (b) false else true;
182182 _ = result;
183183 }
184 comptime {
185 return i;
186 }
184 return comptime i;
187185}
188186
189187test "@setEvalBranchQuota" {
test/cases/compile_errors/branch_in_comptime_only_scope_uses_condbr_inline.zig+3-4
......@@ -16,7 +16,6 @@ pub export fn entry2() void {
1616// backend=stage2
1717// target=native
1818//
19// :4:15: error: unable to resolve comptime value
20// :4:15: note: condition in comptime branch must be comptime-known
21// :11:11: error: unable to resolve comptime value
22// :11:11: note: condition in comptime branch must be comptime-known
19// :4:15: error: unable to evaluate comptime expression
20// :4:13: note: operation is runtime due to this operand
21// :11:11: error: unable to evaluate comptime expression
test/cases/compile_errors/ignored_comptime_value.zig+4-10
......@@ -5,13 +5,7 @@ export fn b() void {
55 comptime bar();
66}
77fn bar() u8 {
8 const u32_max = @import("std").math.maxInt(u32);
9
10 @setEvalBranchQuota(u32_max);
11 var x: u32 = 0;
12 while (x != u32_max) : (x +%= 1) {}
13
14 return 0;
8 return 2;
159}
1610
1711// error
......@@ -21,6 +15,6 @@ fn bar() u8 {
2115// :2:5: error: value of type 'comptime_int' ignored
2216// :2:5: note: all non-void values must be used
2317// :2:5: note: this error can be suppressed by assigning the value to '_'
24// :5:17: error: value of type 'u8' ignored
25// :5:17: note: all non-void values must be used
26// :5:17: note: this error can be suppressed by assigning the value to '_'
18// :5:5: error: value of type 'u8' ignored
19// :5:5: note: all non-void values must be used
20// :5:5: note: this error can be suppressed by assigning the value to '_'
test/src/Cases.zig+3-3
......@@ -718,7 +718,7 @@ const TestManifestConfigDefaults = struct {
718718 if (@"type" == .@"error") {
719719 return "native";
720720 }
721 comptime {
721 return comptime blk: {
722722 var defaults: []const u8 = "";
723723 // TODO should we only return "mainstream" targets by default here?
724724 // TODO we should also specify ABIs explicitly as the backends are
......@@ -735,8 +735,8 @@ const TestManifestConfigDefaults = struct {
735735 defaults = defaults ++ "x86_64-windows" ++ ",";
736736 // Wasm
737737 defaults = defaults ++ "wasm32-wasi";
738 return defaults;
739 }
738 break :blk defaults;
739 };
740740 } else if (std.mem.eql(u8, key, "output_mode")) {
741741 return switch (@"type") {
742742 .@"error" => "Obj",