authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-24 21:45:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-24 21:47:18-07:00
logbcf2eb1a003d076c166d4ce9cba20f6ed9b53887
tree0703024c1c2d2601cd0eee38ac729d01027c8857
parentb802a67562cc912213ebfc6ef8a380c775c999fe

Sema: fix closure capture typeof runtime-known parameter

Closures are not necessarily constant values. For example, Zig code might do something like this: fn foo(x: anytype) void { const S = struct {field: @TypeOf(x)}; } ...in which case the closure_capture instruction has access to a runtime value only. In such case we preserve the type and use a dummy runtime value. closes #11292

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

src/Sema.zig+12-3
......@@ -10483,10 +10483,19 @@ fn zirClosureCapture(
1048310483) CompileError!void {
1048410484 // TODO: Compile error when closed over values are modified
1048510485 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
10486 const tv = try sema.resolveInstConst(block, inst_data.src(), inst_data.operand);
10486 const src = inst_data.src();
10487 // Closures are not necessarily constant values. For example, the
10488 // code might do something like this:
10489 // fn foo(x: anytype) void { const S = struct {field: @TypeOf(x)}; }
10490 // ...in which case the closure_capture instruction has access to a runtime
10491 // value only. In such case we preserve the type and use a dummy runtime value.
10492 const operand = sema.resolveInst(inst_data.operand);
10493 const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) orelse
10494 Value.initTag(.generic_poison);
10495
1048710496 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{
10488 .ty = try tv.ty.copy(sema.perm_arena),
10489 .val = try tv.val.copy(sema.perm_arena),
10497 .ty = try sema.typeOf(operand).copy(sema.perm_arena),
10498 .val = try val.copy(sema.perm_arena),
1049010499 });
1049110500}
1049210501
test/behavior/eval.zig+15
......@@ -878,3 +878,18 @@ test "const local with comptime init through array init" {
878878
879879 try comptime expect(decls[0][0].name[0] == 'a');
880880}
881
882test "closure capture type of runtime-known parameter" {
883 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
884 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
885
886 const S = struct {
887 fn b(c: anytype) !void {
888 const D = struct { c: @TypeOf(c) };
889 var d = D{ .c = c };
890 try expect(d.c == 1234);
891 }
892 };
893 var c: i32 = 1234;
894 try S.b(c);
895}