diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-03-07 18:41:45 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-07 18:41:45 -0800 |
| commit | 97aa5f7b8a059f91b78ce7cd70cba0f3aa2c5118 (patch) | |
| tree | 4e2dc7d8083a24bb01cf8e94e684e3256b7f0a31 /src/type.zig | |
| parent | 377ecc6afb14a112a07c6d2c3570e2b77b12a116 (diff) | |
| parent | 38331b1cabf86586bdf70c80ed98f74c60305160 (diff) | |
| download | zig-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.zig | 382 |
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 }; |
