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
This commit is contained in:
Andrew Kelley 2022-03-24 21:45:22 -07:00
parent b802a67562
commit bcf2eb1a00
2 changed files with 27 additions and 3 deletions

View File

@ -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),
});
}

View File

@ -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);
}