Commit e864c38cc3

mlugg <mlugg@mlugg.co.uk>
2025-01-22 05:16:16
Sema: fix crash when `inline` loop condition is not comptime-known
1 parent 8470b6e
Changed files (3)
lib
src
test
lib/std/zig.zig
@@ -788,6 +788,7 @@ pub const SimpleComptimeReason = enum(u32) {
     // Miscellaneous reasons.
     comptime_keyword,
     comptime_call_modifier,
+    inline_loop_operand,
     switch_item,
     tuple_field_default_value,
     struct_field_default_value,
@@ -863,6 +864,7 @@ pub const SimpleComptimeReason = enum(u32) {
 
             .comptime_keyword             => "'comptime' keyword forces comptime evaluation",
             .comptime_call_modifier       => "'.compile_time' call modifier forces comptime evaluation",
+            .inline_loop_operand          => "inline loop condition must be comptime-known",
             .switch_item                  => "switch prong values must be comptime-known",
             .tuple_field_default_value    => "tuple field default value must be comptime-known",
             .struct_field_default_value   => "struct field default value must be comptime-known",
src/Sema.zig
@@ -1824,7 +1824,14 @@ fn analyzeBodyInner(
                 );
                 const uncasted_cond = try sema.resolveInst(extra.data.condition);
                 const cond = try sema.coerce(block, Type.bool, uncasted_cond, cond_src);
-                const cond_val = try sema.resolveConstDefinedValue(block, cond_src, cond, null);
+                const cond_val = try sema.resolveConstDefinedValue(
+                    block,
+                    cond_src,
+                    cond,
+                    // If this block is comptime, it's more helpful to just give the outer message.
+                    // This is particularly true if this came from a comptime `condbr` above.
+                    if (block.isComptime()) null else .{ .simple = .inline_loop_operand },
+                );
                 const inline_body = if (cond_val.toBool()) then_body else else_body;
 
                 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
test/cases/compile_errors/runtime_condition_in_inline_loop.zig
@@ -0,0 +1,16 @@
+var rt_slice: []const u8 = &.{ 1, 2, 3 };
+
+export fn foo() void {
+    inline for (rt_slice) |_| {}
+}
+
+export fn bar() void {
+    inline while (rt_slice.len == 0) {}
+}
+
+// error
+//
+// :4:17: error: unable to resolve comptime value
+// :4:17: note: inline loop condition must be comptime-known
+// :8:32: error: unable to resolve comptime value
+// :8:32: note: inline loop condition must be comptime-known