aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-03-07 18:41:45 -0800
committerGitHub <noreply@github.com>2024-03-07 18:41:45 -0800
commit97aa5f7b8a059f91b78ce7cd70cba0f3aa2c5118 (patch)
tree4e2dc7d8083a24bb01cf8e94e684e3256b7f0a31 /src/type.zig
parent377ecc6afb14a112a07c6d2c3570e2b77b12a116 (diff)
parent38331b1cabf86586bdf70c80ed98f74c60305160 (diff)
downloadzig-97aa5f7b8a059f91b78ce7cd70cba0f3aa2c5118.tar.gz
zig-97aa5f7b8a059f91b78ce7cd70cba0f3aa2c5118.zip
Merge pull request #19190 from mlugg/struct-equivalence
compiler: namespace type equivalence based on AST node + captures
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig382
1 files changed, 204 insertions, 178 deletions
diff --git a/src/type.zig b/src/type.zig
index b038d7a021..8b2c6f2a1e 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -320,11 +320,12 @@ pub const Type = struct {
.generic_poison => unreachable,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.decl.unwrap()) |decl_index| {
const decl = mod.declPtr(decl_index);
try decl.renderFullyQualifiedName(mod, writer);
- } else if (struct_type.namespace.unwrap()) |namespace_index| {
+ } else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| {
const namespace = mod.namespacePtr(namespace_index);
try namespace.renderFullyQualifiedName(mod, .empty, writer);
} else {
@@ -354,16 +355,16 @@ pub const Type = struct {
try writer.writeAll("}");
},
- .union_type => |union_type| {
- const decl = mod.declPtr(union_type.decl);
+ .union_type => {
+ const decl = mod.declPtr(ip.loadUnionType(ty.toIntern()).decl);
try decl.renderFullyQualifiedName(mod, writer);
},
- .opaque_type => |opaque_type| {
- const decl = mod.declPtr(opaque_type.decl);
+ .opaque_type => {
+ const decl = mod.declPtr(ip.loadOpaqueType(ty.toIntern()).decl);
try decl.renderFullyQualifiedName(mod, writer);
},
- .enum_type => |enum_type| {
- const decl = mod.declPtr(enum_type.decl);
+ .enum_type => {
+ const decl = mod.declPtr(ip.loadEnumType(ty.toIntern()).decl);
try decl.renderFullyQualifiedName(mod, writer);
},
.func_type => |fn_info| {
@@ -573,7 +574,8 @@ pub const Type = struct {
.generic_poison => unreachable,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {
// In this case, we guess that hasRuntimeBits() for this type is true,
// and then later if our guess was incorrect, we emit a compile error.
@@ -601,7 +603,8 @@ pub const Type = struct {
return false;
},
- .union_type => |union_type| {
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
switch (union_type.flagsPtr(ip).runtime_tag) {
.none => {
if (union_type.flagsPtr(ip).status == .field_types_wip) {
@@ -628,9 +631,8 @@ pub const Type = struct {
.lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes())
return error.NeedLazy,
}
- const union_obj = ip.loadUnionType(union_type);
- for (0..union_obj.field_types.len) |field_index| {
- const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
+ for (0..union_type.field_types.len) |field_index| {
+ const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
return true;
} else {
@@ -639,7 +641,7 @@ pub const Type = struct {
},
.opaque_type => true,
- .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
+ .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
// values, not types
.undef,
@@ -736,15 +738,19 @@ pub const Type = struct {
.generic_poison,
=> false,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
// Struct with no fields have a well-defined layout of no bits.
return struct_type.layout != .Auto or struct_type.field_types.len == 0;
},
- .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) {
- .none, .safety => union_type.flagsPtr(ip).layout != .Auto,
- .tagged => false,
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
+ return switch (union_type.flagsPtr(ip).runtime_tag) {
+ .none, .safety => union_type.flagsPtr(ip).layout != .Auto,
+ .tagged => false,
+ };
},
- .enum_type => |enum_type| switch (enum_type.tag_mode) {
+ .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
.auto => false,
.explicit, .nonexhaustive => true,
},
@@ -1019,7 +1025,8 @@ pub const Type = struct {
.noreturn => unreachable,
.generic_poison => unreachable,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.layout == .Packed) {
switch (strat) {
.sema => |sema| try sema.resolveTypeLayout(ty),
@@ -1066,7 +1073,8 @@ pub const Type = struct {
}
return .{ .scalar = big_align };
},
- .union_type => |union_type| {
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
const flags = union_type.flagsPtr(ip).*;
if (flags.alignment != .none) return .{ .scalar = flags.alignment };
@@ -1082,8 +1090,8 @@ pub const Type = struct {
return .{ .scalar = union_type.flagsPtr(ip).alignment };
},
.opaque_type => return .{ .scalar = .@"1" },
- .enum_type => |enum_type| return .{
- .scalar = Type.fromInterned(enum_type.tag_ty).abiAlignment(mod),
+ .enum_type => return .{
+ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(mod),
},
// values, not types
@@ -1394,7 +1402,8 @@ pub const Type = struct {
.noreturn => unreachable,
.generic_poison => unreachable,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
switch (strat) {
.sema => |sema| try sema.resolveTypeLayout(ty),
.lazy => switch (struct_type.layout) {
@@ -1439,7 +1448,8 @@ pub const Type = struct {
return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
},
- .union_type => |union_type| {
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
switch (strat) {
.sema => |sema| try sema.resolveTypeLayout(ty),
.lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{
@@ -1455,7 +1465,7 @@ pub const Type = struct {
return .{ .scalar = union_type.size(ip).* };
},
.opaque_type => unreachable, // no size available
- .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = Type.fromInterned(enum_type.tag_ty).abiSize(mod) },
+ .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(mod) },
// values, not types
.undef,
@@ -1644,7 +1654,8 @@ pub const Type = struct {
.extern_options => unreachable,
.type_info => unreachable,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
const is_packed = struct_type.layout == .Packed;
if (opt_sema) |sema| {
try sema.resolveTypeFields(ty);
@@ -1661,7 +1672,8 @@ pub const Type = struct {
return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
},
- .union_type => |union_type| {
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
const is_packed = ty.containerLayout(mod) == .Packed;
if (opt_sema) |sema| {
try sema.resolveTypeFields(ty);
@@ -1670,19 +1682,18 @@ pub const Type = struct {
if (!is_packed) {
return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
}
- const union_obj = ip.loadUnionType(union_type);
- assert(union_obj.flagsPtr(ip).status.haveFieldTypes());
+ assert(union_type.flagsPtr(ip).status.haveFieldTypes());
var size: u64 = 0;
- for (0..union_obj.field_types.len) |field_index| {
- const field_ty = union_obj.field_types.get(ip)[field_index];
+ for (0..union_type.field_types.len) |field_index| {
+ const field_ty = union_type.field_types.get(ip)[field_index];
size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema));
}
return size;
},
.opaque_type => unreachable,
- .enum_type => |enum_type| return bitSizeAdvanced(Type.fromInterned(enum_type.tag_ty), mod, opt_sema),
+ .enum_type => return bitSizeAdvanced(Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), mod, opt_sema),
// values, not types
.undef,
@@ -1713,8 +1724,8 @@ pub const Type = struct {
pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.haveLayout(ip),
- .union_type => |union_type| union_type.haveLayout(ip),
+ .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip),
+ .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip),
.array_type => |array_type| {
if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true;
return Type.fromInterned(array_type.child).layoutIsResolved(mod);
@@ -1914,16 +1925,18 @@ pub const Type = struct {
/// Otherwise, returns `null`.
pub fn unionTagType(ty: Type, mod: *Module) ?Type {
const ip = &mod.intern_pool;
- return switch (ip.indexToKey(ty.toIntern())) {
- .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) {
- .tagged => {
- assert(union_type.flagsPtr(ip).status.haveFieldTypes());
- return Type.fromInterned(union_type.enum_tag_ty);
- },
- else => null,
+ switch (ip.indexToKey(ty.toIntern())) {
+ .union_type => {},
+ else => return null,
+ }
+ const union_type = ip.loadUnionType(ty.toIntern());
+ switch (union_type.flagsPtr(ip).runtime_tag) {
+ .tagged => {
+ assert(union_type.flagsPtr(ip).status.haveFieldTypes());
+ return Type.fromInterned(union_type.enum_tag_ty);
},
- else => null,
- };
+ else => return null,
+ }
}
/// Same as `unionTagType` but includes safety tag.
@@ -1931,7 +1944,8 @@ pub const Type = struct {
pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .union_type => |union_type| {
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
if (!union_type.hasTag(ip)) return null;
assert(union_type.haveFieldTypes(ip));
return Type.fromInterned(union_type.enum_tag_ty);
@@ -1981,17 +1995,16 @@ pub const Type = struct {
pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout {
const ip = &mod.intern_pool;
- const union_type = ip.indexToKey(ty.toIntern()).union_type;
- const union_obj = ip.loadUnionType(union_type);
+ const union_obj = ip.loadUnionType(ty.toIntern());
return mod.getUnionLayout(union_obj);
}
pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.layout,
+ .struct_type => ip.loadStructType(ty.toIntern()).layout,
.anon_struct_type => .Auto,
- .union_type => |union_type| union_type.flagsPtr(ip).layout,
+ .union_type => ip.loadUnionType(ty.toIntern()).flagsPtr(ip).layout,
else => unreachable,
};
}
@@ -2095,22 +2108,15 @@ pub const Type = struct {
/// Asserts the type is an array or vector or struct.
pub fn arrayLen(ty: Type, mod: *const Module) u64 {
- return arrayLenIp(ty, &mod.intern_pool);
+ return ty.arrayLenIp(&mod.intern_pool);
}
pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
- return switch (ip.indexToKey(ty.toIntern())) {
- .vector_type => |vector_type| vector_type.len,
- .array_type => |array_type| array_type.len,
- .struct_type => |struct_type| struct_type.field_types.len,
- .anon_struct_type => |tuple| tuple.types.len,
-
- else => unreachable,
- };
+ return ip.aggregateTypeLen(ty.toIntern());
}
pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {
- return ty.arrayLen(mod) + @intFromBool(ty.sentinel(mod) != null);
+ return mod.intern_pool.aggregateTypeLenIncludingSentinel(ty.toIntern());
}
pub fn vectorLen(ty: Type, mod: *const Module) u32 {
@@ -2199,8 +2205,8 @@ pub const Type = struct {
.c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
else => switch (ip.indexToKey(ty.toIntern())) {
.int_type => |int_type| return int_type,
- .struct_type => |t| ty = Type.fromInterned(t.backingIntType(ip).*),
- .enum_type => |enum_type| ty = Type.fromInterned(enum_type.tag_ty),
+ .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntType(ip).*),
+ .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
.vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),
.error_set_type, .inferred_error_set_type => {
@@ -2463,7 +2469,8 @@ pub const Type = struct {
.generic_poison => unreachable,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
assert(struct_type.haveFieldTypes(ip));
if (struct_type.knownNonOpv(ip))
return null;
@@ -2505,11 +2512,11 @@ pub const Type = struct {
} })));
},
- .union_type => |union_type| {
- const union_obj = ip.loadUnionType(union_type);
+ .union_type => {
+ const union_obj = ip.loadUnionType(ty.toIntern());
const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse
return null;
- if (union_obj.field_names.len == 0) {
+ if (union_obj.field_types.len == 0) {
const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
return Value.fromInterned(only);
}
@@ -2524,45 +2531,48 @@ pub const Type = struct {
return Value.fromInterned(only);
},
.opaque_type => return null,
- .enum_type => |enum_type| switch (enum_type.tag_mode) {
- .nonexhaustive => {
- if (enum_type.tag_ty == .comptime_int_type) return null;
-
- if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
- const only = try mod.intern(.{ .enum_tag = .{
- .ty = ty.toIntern(),
- .int = int_opv.toIntern(),
- } });
- return Value.fromInterned(only);
- }
+ .enum_type => {
+ const enum_type = ip.loadEnumType(ty.toIntern());
+ switch (enum_type.tag_mode) {
+ .nonexhaustive => {
+ if (enum_type.tag_ty == .comptime_int_type) return null;
+
+ if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
+ const only = try mod.intern(.{ .enum_tag = .{
+ .ty = ty.toIntern(),
+ .int = int_opv.toIntern(),
+ } });
+ return Value.fromInterned(only);
+ }
- return null;
- },
- .auto, .explicit => {
- if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
+ return null;
+ },
+ .auto, .explicit => {
+ if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
- switch (enum_type.names.len) {
- 0 => {
- const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
- return Value.fromInterned(only);
- },
- 1 => {
- if (enum_type.values.len == 0) {
- const only = try mod.intern(.{ .enum_tag = .{
- .ty = ty.toIntern(),
- .int = try mod.intern(.{ .int = .{
- .ty = enum_type.tag_ty,
- .storage = .{ .u64 = 0 },
- } }),
- } });
+ switch (enum_type.names.len) {
+ 0 => {
+ const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
return Value.fromInterned(only);
- } else {
- return Value.fromInterned(enum_type.values.get(ip)[0]);
- }
- },
- else => return null,
- }
- },
+ },
+ 1 => {
+ if (enum_type.values.len == 0) {
+ const only = try mod.intern(.{ .enum_tag = .{
+ .ty = ty.toIntern(),
+ .int = try mod.intern(.{ .int = .{
+ .ty = enum_type.tag_ty,
+ .storage = .{ .u64 = 0 },
+ } }),
+ } });
+ return Value.fromInterned(only);
+ } else {
+ return Value.fromInterned(enum_type.values.get(ip)[0]);
+ }
+ },
+ else => return null,
+ }
+ },
+ }
},
// values, not types
@@ -2676,7 +2686,8 @@ pub const Type = struct {
.type_info,
=> true,
},
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
// packed structs cannot be comptime-only because they have a well-defined
// memory layout and every field has a well-defined bit pattern.
if (struct_type.layout == .Packed)
@@ -2726,38 +2737,40 @@ pub const Type = struct {
return false;
},
- .union_type => |union_type| switch (union_type.flagsPtr(ip).requires_comptime) {
- .no, .wip => false,
- .yes => true,
- .unknown => {
- // The type is not resolved; assert that we have a Sema.
- const sema = opt_sema.?;
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
+ switch (union_type.flagsPtr(ip).requires_comptime) {
+ .no, .wip => return false,
+ .yes => return true,
+ .unknown => {
+ // The type is not resolved; assert that we have a Sema.
+ const sema = opt_sema.?;
- if (union_type.flagsPtr(ip).status == .field_types_wip)
- return false;
+ if (union_type.flagsPtr(ip).status == .field_types_wip)
+ return false;
- union_type.flagsPtr(ip).requires_comptime = .wip;
- errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
+ union_type.flagsPtr(ip).requires_comptime = .wip;
+ errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
- try sema.resolveTypeFieldsUnion(ty, union_type);
+ try sema.resolveTypeFieldsUnion(ty, union_type);
- const union_obj = ip.loadUnionType(union_type);
- for (0..union_obj.field_types.len) |field_idx| {
- const field_ty = union_obj.field_types.get(ip)[field_idx];
- if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
- union_obj.flagsPtr(ip).requires_comptime = .yes;
- return true;
+ for (0..union_type.field_types.len) |field_idx| {
+ const field_ty = union_type.field_types.get(ip)[field_idx];
+ if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
+ union_type.flagsPtr(ip).requires_comptime = .yes;
+ return true;
+ }
}
- }
- union_obj.flagsPtr(ip).requires_comptime = .no;
- return false;
- },
+ union_type.flagsPtr(ip).requires_comptime = .no;
+ return false;
+ },
+ }
},
.opaque_type => false,
- .enum_type => |enum_type| return Type.fromInterned(enum_type.tag_ty).comptimeOnlyAdvanced(mod, opt_sema),
+ .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyAdvanced(mod, opt_sema),
// values, not types
.undef,
@@ -2830,11 +2843,12 @@ pub const Type = struct {
/// Returns null if the type has no namespace.
pub fn getNamespaceIndex(ty: Type, mod: *Module) InternPool.OptionalNamespaceIndex {
- return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
- .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
- .struct_type => |struct_type| struct_type.namespace,
- .union_type => |union_type| union_type.namespace.toOptional(),
- .enum_type => |enum_type| enum_type.namespace,
+ const ip = &mod.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace,
+ .struct_type => ip.loadStructType(ty.toIntern()).namespace,
+ .union_type => ip.loadUnionType(ty.toIntern()).namespace,
+ .enum_type => ip.loadEnumType(ty.toIntern()).namespace,
else => .none,
};
@@ -2920,16 +2934,18 @@ pub const Type = struct {
/// Asserts the type is an enum or a union.
pub fn intTagType(ty: Type, mod: *Module) Type {
- return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
- .union_type => |union_type| Type.fromInterned(union_type.enum_tag_ty).intTagType(mod),
- .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty),
+ const ip = &mod.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(mod),
+ .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
else => unreachable,
};
}
pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
- return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
- .enum_type => |enum_type| switch (enum_type.tag_mode) {
+ const ip = &mod.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
.nonexhaustive => true,
.auto, .explicit => false,
},
@@ -2953,21 +2969,21 @@ pub const Type = struct {
}
pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
- return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
+ return mod.intern_pool.loadEnumType(ty.toIntern()).names;
}
pub fn enumFieldCount(ty: Type, mod: *Module) usize {
- return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names.len;
+ return mod.intern_pool.loadEnumType(ty.toIntern()).names.len;
}
pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
const ip = &mod.intern_pool;
- return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip)[field_index];
+ return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index];
}
pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
const ip = &mod.intern_pool;
- const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
+ const enum_type = ip.loadEnumType(ty.toIntern());
return enum_type.nameIndex(ip, field_name);
}
@@ -2976,7 +2992,7 @@ pub const Type = struct {
/// declaration order, or `null` if `enum_tag` does not match any field.
pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
const ip = &mod.intern_pool;
- const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
+ const enum_type = ip.loadEnumType(ty.toIntern());
const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
.int => enum_tag.toIntern(),
.enum_tag => |info| info.int,
@@ -2990,7 +3006,7 @@ pub const Type = struct {
pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.fieldName(ip, field_index),
+ .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index),
.anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index),
else => unreachable,
};
@@ -3010,7 +3026,7 @@ pub const Type = struct {
pub fn structFieldCount(ty: Type, mod: *Module) u32 {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.field_types.len,
+ .struct_type => ip.loadStructType(ty.toIntern()).field_types.len,
.anon_struct_type => |anon_struct| anon_struct.types.len,
else => unreachable,
};
@@ -3020,9 +3036,9 @@ pub const Type = struct {
pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| Type.fromInterned(struct_type.field_types.get(ip)[index]),
- .union_type => |union_type| {
- const union_obj = ip.loadUnionType(union_type);
+ .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]),
+ .union_type => {
+ const union_obj = ip.loadUnionType(ty.toIntern());
return Type.fromInterned(union_obj.field_types.get(ip)[index]);
},
.anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),
@@ -3033,7 +3049,8 @@ pub const Type = struct {
pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) Alignment {
const ip = &mod.intern_pool;
switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
assert(struct_type.layout != .Packed);
const explicit_align = struct_type.fieldAlign(ip, index);
const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
@@ -3042,8 +3059,8 @@ pub const Type = struct {
.anon_struct_type => |anon_struct| {
return Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignment(mod);
},
- .union_type => |union_type| {
- const union_obj = ip.loadUnionType(union_type);
+ .union_type => {
+ const union_obj = ip.loadUnionType(ty.toIntern());
return mod.unionFieldNormalAlignment(union_obj, @intCast(index));
},
else => unreachable,
@@ -3053,7 +3070,8 @@ pub const Type = struct {
pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
const ip = &mod.intern_pool;
switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
const val = struct_type.fieldInit(ip, index);
// TODO: avoid using `unreachable` to indicate this.
if (val == .none) return Value.@"unreachable";
@@ -3072,7 +3090,8 @@ pub const Type = struct {
pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
const ip = &mod.intern_pool;
switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.fieldIsComptime(ip, index)) {
assert(struct_type.haveFieldInits(ip));
return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
@@ -3095,7 +3114,7 @@ pub const Type = struct {
pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.fieldIsComptime(ip, index),
+ .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),
.anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,
else => unreachable,
};
@@ -3110,7 +3129,8 @@ pub const Type = struct {
pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
const ip = &mod.intern_pool;
switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
assert(struct_type.haveLayout(ip));
assert(struct_type.layout != .Packed);
return struct_type.offsets.get(ip)[index];
@@ -3137,11 +3157,11 @@ pub const Type = struct {
return offset;
},
- .union_type => |union_type| {
+ .union_type => {
+ const union_type = ip.loadUnionType(ty.toIntern());
if (!union_type.hasTag(ip))
return 0;
- const union_obj = ip.loadUnionType(union_type);
- const layout = mod.getUnionLayout(union_obj);
+ const layout = mod.getUnionLayout(union_type);
if (layout.tag_align.compare(.gte, layout.payload_align)) {
// {Tag, Payload}
return layout.payload_align.forward(layout.tag_size);
@@ -3160,17 +3180,8 @@ pub const Type = struct {
}
pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {
- return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
- return mod.declPtr(struct_type.decl.unwrap() orelse return null).srcLoc(mod);
- },
- .union_type => |union_type| {
- return mod.declPtr(union_type.decl).srcLoc(mod);
- },
- .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type),
- .enum_type => |enum_type| mod.declPtr(enum_type.decl).srcLoc(mod),
- else => null,
- };
+ const decl = ty.getOwnerDeclOrNull(mod) orelse return null;
+ return mod.declPtr(decl).srcLoc(mod);
}
pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex {
@@ -3178,11 +3189,12 @@ pub const Type = struct {
}
pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?InternPool.DeclIndex {
- return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.decl.unwrap(),
- .union_type => |union_type| union_type.decl,
- .opaque_type => |opaque_type| opaque_type.decl,
- .enum_type => |enum_type| enum_type.decl,
+ const ip = &mod.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .struct_type => ip.loadStructType(ty.toIntern()).decl.unwrap(),
+ .union_type => ip.loadUnionType(ty.toIntern()).decl,
+ .opaque_type => ip.loadOpaqueType(ty.toIntern()).decl,
+ .enum_type => ip.loadEnumType(ty.toIntern()).decl,
else => null,
};
}
@@ -3194,7 +3206,8 @@ pub const Type = struct {
pub fn isTuple(ty: Type, mod: *Module) bool {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.layout == .Packed) return false;
if (struct_type.decl == .none) return false;
return struct_type.flagsPtr(ip).is_tuple;
@@ -3215,7 +3228,8 @@ pub const Type = struct {
pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.layout == .Packed) return false;
if (struct_type.decl == .none) return false;
return struct_type.flagsPtr(ip).is_tuple;
@@ -3262,16 +3276,28 @@ pub const Type = struct {
}
pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
- return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
- inline .struct_type,
- .union_type,
- .enum_type,
- .opaque_type,
- => |info| info.zir_index.unwrap(),
+ const ip = &zcu.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),
+ .union_type => ip.loadUnionType(ty.toIntern()).zir_index,
+ .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),
+ .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,
else => null,
};
}
+ /// Given a namespace type, returns its list of caotured values.
+ pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice {
+ const ip = &zcu.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .struct_type => ip.loadStructType(ty.toIntern()).captures,
+ .union_type => ip.loadUnionType(ty.toIntern()).captures,
+ .enum_type => ip.loadEnumType(ty.toIntern()).captures,
+ .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures,
+ else => unreachable,
+ };
+ }
+
pub const @"u1": Type = .{ .ip_index = .u1_type };
pub const @"u8": Type = .{ .ip_index = .u8_type };
pub const @"u16": Type = .{ .ip_index = .u16_type };