From 2c4ac44f25743f5b7ae9db6bc570ab71f15fd83b Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 5 Mar 2024 07:22:47 +0000 Subject: compiler: treat decl_val/decl_ref of potentially generic decls as captures This fixes an issue with the implementation of #18816. Consider the following code: ```zig pub fn Wrap(comptime T: type) type { return struct { pub const T1 = T; inner: struct { x: T1 }, }; } ``` Previously, the type of `inner` was not considered to be "capturing" any value, as `T1` is a decl. However, since it is declared within a generic function, this decl reference depends on the context, and thus should be treated as a capture. AstGen has been augmented to tunnel references to decls through closure when the decl was declared in a potentially-generic context (i.e. within a function). --- src/InternPool.zig | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/InternPool.zig') diff --git a/src/InternPool.zig b/src/InternPool.zig index 36311100da..6639603cb5 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -503,22 +503,29 @@ pub const OptionalNullTerminatedString = enum(u32) { }; /// A single value captured in the closure of a namespace type. This is not a plain -/// `Index` because we must differentiate between runtime-known values (where we -/// store the type) and comptime-known values (where we store the value). +/// `Index` because we must differentiate between the following cases: +/// * runtime-known value (where we store the type) +/// * comptime-known value (where we store the value) +/// * decl val (so that we can analyze the value lazily) +/// * decl ref (so that we can analyze the reference lazily) pub const CaptureValue = packed struct(u32) { - tag: enum { @"comptime", runtime }, - idx: u31, + tag: enum { @"comptime", runtime, decl_val, decl_ref }, + idx: u30, pub fn wrap(val: Unwrapped) CaptureValue { return switch (val) { .@"comptime" => |i| .{ .tag = .@"comptime", .idx = @intCast(@intFromEnum(i)) }, .runtime => |i| .{ .tag = .runtime, .idx = @intCast(@intFromEnum(i)) }, + .decl_val => |i| .{ .tag = .decl_val, .idx = @intCast(@intFromEnum(i)) }, + .decl_ref => |i| .{ .tag = .decl_ref, .idx = @intCast(@intFromEnum(i)) }, }; } pub fn unwrap(val: CaptureValue) Unwrapped { return switch (val.tag) { .@"comptime" => .{ .@"comptime" = @enumFromInt(val.idx) }, .runtime => .{ .runtime = @enumFromInt(val.idx) }, + .decl_val => .{ .decl_val = @enumFromInt(val.idx) }, + .decl_ref => .{ .decl_ref = @enumFromInt(val.idx) }, }; } @@ -527,6 +534,8 @@ pub const CaptureValue = packed struct(u32) { @"comptime": Index, /// Index refers to the type. runtime: Index, + decl_val: DeclIndex, + decl_ref: DeclIndex, }; pub const Slice = struct { -- cgit v1.2.3