Commit 40c4c25e2b

Andrew Kelley <andrew@ziglang.org>
2023-02-19 02:56:37
Sema: add missing coercion when checking for loop len
1 parent 12a7a0d
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -3934,12 +3934,13 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
             .for_node_offset = inst_data.src_node,
             .input_index = i,
         } };
-        const arg_len = if (is_int) object else l: {
+        const arg_len_uncoerced = if (is_int) object else l: {
             try checkIndexable(sema, block, arg_src, object_ty);
             if (!object_ty.indexableHasLen()) continue;
 
             break :l try sema.fieldVal(block, arg_src, object, "len", arg_src);
         };
+        const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src);
         if (len == .none) {
             len = arg_len;
             len_idx = i;
test/behavior/for.zig
@@ -397,3 +397,65 @@ test "raw pointer and counter" {
     try expect(buf[2] == 'C');
     try expect(buf[3] == 'D');
 }
+
+test "inline for with slice as the comptime-known" {
+    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    const comptime_slice = "hello";
+    var runtime_i: usize = 3;
+
+    const S = struct {
+        var ok: usize = 0;
+        fn check(comptime a: u8, b: usize) !void {
+            if (a == 'l') {
+                try expect(b == 3);
+                ok += 1;
+            } else if (a == 'o') {
+                try expect(b == 4);
+                ok += 1;
+            } else {
+                @compileError("fail");
+            }
+        }
+    };
+
+    inline for (comptime_slice[3..5], runtime_i..5) |a, b| {
+        try S.check(a, b);
+    }
+
+    try expect(S.ok == 2);
+}
+
+test "inline for with counter as the comptime-known" {
+    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    var runtime_slice = "hello";
+    var runtime_i: usize = 3;
+
+    const S = struct {
+        var ok: usize = 0;
+        fn check(a: u8, comptime b: usize) !void {
+            if (b == 3) {
+                try expect(a == 'l');
+                ok += 1;
+            } else if (b == 4) {
+                try expect(a == 'o');
+                ok += 1;
+            } else {
+                @compileError("fail");
+            }
+        }
+    };
+
+    inline for (runtime_slice[runtime_i..5], 3..5) |a, b| {
+        try S.check(a, b);
+    }
+
+    try expect(S.ok == 2);
+}