diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-03-24 21:45:22 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-24 21:47:18 -0700 |
| commit | bcf2eb1a003d076c166d4ce9cba20f6ed9b53887 (patch) | |
| tree | 0703024c1c2d2601cd0eee38ac729d01027c8857 | |
| parent | b802a67562cc912213ebfc6ef8a380c775c999fe (diff) | |
| download | zig-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.zig | 15 | ||||
| -rw-r--r-- | test/behavior/eval.zig | 15 |
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); +} |
