From 40c4c25e2b5e2242c3180cd8564dc22697bf363f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 18 Feb 2023 18:56:37 -0700 Subject: [PATCH] Sema: add missing coercion when checking for loop len --- src/Sema.zig | 3 ++- test/behavior/for.zig | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/Sema.zig b/src/Sema.zig index 6e8d77475e..fcdb1ce518 100644 --- a/src/Sema.zig +++ b/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; diff --git a/test/behavior/for.zig b/test/behavior/for.zig index 0c5ab392f4..67a20e4840 100644 --- a/test/behavior/for.zig +++ b/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); +}