aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-24 21:45:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-24 21:47:18 -0700
commitbcf2eb1a003d076c166d4ce9cba20f6ed9b53887 (patch)
tree0703024c1c2d2601cd0eee38ac729d01027c8857
parentb802a67562cc912213ebfc6ef8a380c775c999fe (diff)
downloadzig-bcf2eb1a003d076c166d4ce9cba20f6ed9b53887.tar.gz
zig-bcf2eb1a003d076c166d4ce9cba20f6ed9b53887.zip
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
-rw-r--r--src/Sema.zig15
-rw-r--r--test/behavior/eval.zig15
2 files changed, 27 insertions, 3 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 03a51dc20d..a42a4caf38 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -10483,10 +10483,19 @@ fn zirClosureCapture(
) CompileError!void {
// TODO: Compile error when closed over values are modified
const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
- const tv = try sema.resolveInstConst(block, inst_data.src(), inst_data.operand);
+ const src = inst_data.src();
+ // Closures are not necessarily constant values. For example, the
+ // 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.
+ const operand = sema.resolveInst(inst_data.operand);
+ const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) orelse
+ Value.initTag(.generic_poison);
+
try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{
- .ty = try tv.ty.copy(sema.perm_arena),
- .val = try tv.val.copy(sema.perm_arena),
+ .ty = try sema.typeOf(operand).copy(sema.perm_arena),
+ .val = try val.copy(sema.perm_arena),
});
}
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
index 0328111daa..e3024a3895 100644
--- a/test/behavior/eval.zig
+++ b/test/behavior/eval.zig
@@ -878,3 +878,18 @@ test "const local with comptime init through array init" {
try comptime expect(decls[0][0].name[0] == 'a');
}
+
+test "closure capture type of runtime-known parameter" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn b(c: anytype) !void {
+ const D = struct { c: @TypeOf(c) };
+ var d = D{ .c = c };
+ try expect(d.c == 1234);
+ }
+ };
+ var c: i32 = 1234;
+ try S.b(c);
+}