authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-05 20:33:39+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-05 21:17:40+00:00
logfbbf34e563a376ea1654dce827b9194ba7211b3a
treedc95e30f87d14c2ff3b3784df76ed10327f4425a
parentcac814cf58ca65ffd8081dca6f2f5b26d822ef5d
signaturelock-open Commit is signed but in an unrecognized format.

Sema: disable runtime safety checks in comptime blocks

Sometimes we emit runtime instructions in comptime scopes. These instructions will be discarded, but they allow comptime blocks to contain intermediate runtime-known values, which is necessary for expressions like `runtime_array.len` to work. Since we will always throw away these runtime instructions, including safety checks is a time waste at best and trips an assertion at worst! Resolves: #20064

2 files changed, 24 insertions(+), 3 deletions(-)

src/Sema.zig+13-3
...@@ -504,7 +504,17 @@ pub const Block = struct {...@@ -504,7 +504,17 @@ pub const Block = struct {
504 };504 };
505 }505 }
506506
507 pub fn wantSafety(block: *const Block) bool {507 fn wantSafeTypes(block: *const Block) bool {
508 return block.want_safety orelse switch (block.sema.pt.zcu.optimizeMode()) {
509 .Debug => true,
510 .ReleaseSafe => true,
511 .ReleaseFast => false,
512 .ReleaseSmall => false,
513 };
514 }
515
516 fn wantSafety(block: *const Block) bool {
517 if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks
508 return block.want_safety orelse switch (block.sema.pt.zcu.optimizeMode()) {518 return block.want_safety orelse switch (block.sema.pt.zcu.optimizeMode()) {
509 .Debug => true,519 .Debug => true,
510 .ReleaseSafe => true,520 .ReleaseSafe => true,
...@@ -3294,7 +3304,7 @@ fn zirUnionDecl(...@@ -3294,7 +3304,7 @@ fn zirUnionDecl(
3294 .tagged3304 .tagged
3295 else if (small.layout != .auto)3305 else if (small.layout != .auto)
3296 .none3306 .none
3297 else switch (block.wantSafety()) {3307 else switch (block.wantSafeTypes()) {
3298 true => .safety,3308 true => .safety,
3299 false => .none,3309 false => .none,
3300 },3310 },
...@@ -22219,7 +22229,7 @@ fn reifyUnion(...@@ -22219,7 +22229,7 @@ fn reifyUnion(
22219 .tagged22229 .tagged
22220 else if (layout != .auto)22230 else if (layout != .auto)
22221 .none22231 .none
22222 else switch (block.wantSafety()) {22232 else switch (block.wantSafeTypes()) {
22223 true => .safety,22233 true => .safety,
22224 false => .none,22234 false => .none,
22225 },22235 },
test/behavior/eval.zig+11
...@@ -1751,3 +1751,14 @@ test "comptime labeled block implicit exit" {...@@ -1751,3 +1751,14 @@ test "comptime labeled block implicit exit" {
1751 };1751 };
1752 comptime assert(result == {});1752 comptime assert(result == {});
1753}1753}
1754
1755test "comptime block has intermediate runtime-known values" {
1756 const arr: [2]u8 = .{ 1, 2 };
1757
1758 var idx: usize = undefined;
1759 idx = 0;
1760
1761 comptime {
1762 _ = arr[idx];
1763 }
1764}