mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
InternPool: safer enum API
The key changes in this commit are: ```diff - names: []const NullTerminatedString, + names: NullTerminatedString.Slice, - values: []const Index, + values: Index.Slice, ``` Which eliminates the slices from `InternPool.Key.EnumType` and replaces them with structs that contain `start` and `len` indexes. This makes the lifetime of `EnumType` change from expiring with updates to InternPool, to expiring when the InternPool is garbage-collected, which is currently never. This is gearing up for a larger change I started working on locally which moves union types into InternPool. As a bonus, I fixed some unnecessary instances of `@as`.
This commit is contained in:
parent
8c1329b222
commit
7ef1eb1c27
@ -105,7 +105,7 @@ pub const OptionalMapIndex = enum(u32) {
|
||||
|
||||
pub fn unwrap(oi: OptionalMapIndex) ?MapIndex {
|
||||
if (oi == .none) return null;
|
||||
return @as(MapIndex, @enumFromInt(@intFromEnum(oi)));
|
||||
return @enumFromInt(@intFromEnum(oi));
|
||||
}
|
||||
};
|
||||
|
||||
@ -114,7 +114,7 @@ pub const MapIndex = enum(u32) {
|
||||
_,
|
||||
|
||||
pub fn toOptional(i: MapIndex) OptionalMapIndex {
|
||||
return @as(OptionalMapIndex, @enumFromInt(@intFromEnum(i)));
|
||||
return @enumFromInt(@intFromEnum(i));
|
||||
}
|
||||
};
|
||||
|
||||
@ -218,7 +218,7 @@ pub const OptionalNullTerminatedString = enum(u32) {
|
||||
|
||||
pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString {
|
||||
if (oi == .none) return null;
|
||||
return @as(NullTerminatedString, @enumFromInt(@intFromEnum(oi)));
|
||||
return @enumFromInt(@intFromEnum(oi));
|
||||
}
|
||||
};
|
||||
|
||||
@ -415,11 +415,11 @@ pub const Key = union(enum) {
|
||||
/// explicitly provided tag type or auto-numbered.
|
||||
tag_ty: Index,
|
||||
/// Set of field names in declaration order.
|
||||
names: []const NullTerminatedString,
|
||||
names: NullTerminatedString.Slice,
|
||||
/// Maps integer tag value to field index.
|
||||
/// Entries are in declaration order, same as `fields`.
|
||||
/// If this is empty, it means the enum tags are auto-numbered.
|
||||
values: []const Index,
|
||||
values: Index.Slice,
|
||||
tag_mode: TagMode,
|
||||
/// This is ignored by `get` but will always be provided by `indexToKey`.
|
||||
names_map: OptionalMapIndex = .none,
|
||||
@ -441,9 +441,9 @@ pub const Key = union(enum) {
|
||||
/// Look up field index based on field name.
|
||||
pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
|
||||
const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];
|
||||
const adapter: NullTerminatedString.Adapter = .{ .strings = self.names };
|
||||
const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
|
||||
const field_index = map.getIndexAdapted(name, adapter) orelse return null;
|
||||
return @as(u32, @intCast(field_index));
|
||||
return @intCast(field_index);
|
||||
}
|
||||
|
||||
/// Look up field index based on tag value.
|
||||
@ -461,9 +461,9 @@ pub const Key = union(enum) {
|
||||
};
|
||||
if (self.values_map.unwrap()) |values_map| {
|
||||
const map = &ip.maps.items[@intFromEnum(values_map)];
|
||||
const adapter: Index.Adapter = .{ .indexes = self.values };
|
||||
const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };
|
||||
const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
|
||||
return @as(u32, @intCast(field_index));
|
||||
return @intCast(field_index);
|
||||
}
|
||||
// Auto-numbered enum. Convert `int_tag_val` to field index.
|
||||
const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {
|
||||
@ -497,8 +497,8 @@ pub const Key = union(enum) {
|
||||
.namespace = self.namespace,
|
||||
.tag_ty = self.tag_ty,
|
||||
.tag_mode = self.tag_mode,
|
||||
.names = &.{},
|
||||
.values = &.{},
|
||||
.names = .{ .start = 0, .len = 0 },
|
||||
.values = .{ .start = 0, .len = 0 },
|
||||
};
|
||||
}
|
||||
|
||||
@ -2570,7 +2570,7 @@ pub const Alignment = enum(u6) {
|
||||
pub fn fromByteUnits(n: u64) Alignment {
|
||||
if (n == 0) return .none;
|
||||
assert(std.math.isPowerOfTwo(n));
|
||||
return @as(Alignment, @enumFromInt(@ctz(n)));
|
||||
return @enumFromInt(@ctz(n));
|
||||
}
|
||||
|
||||
pub fn fromNonzeroByteUnits(n: u64) Alignment {
|
||||
@ -2647,11 +2647,11 @@ pub const PackedU64 = packed struct(u64) {
|
||||
b: u32,
|
||||
|
||||
pub fn get(x: PackedU64) u64 {
|
||||
return @as(u64, @bitCast(x));
|
||||
return @bitCast(x);
|
||||
}
|
||||
|
||||
pub fn init(x: u64) PackedU64 {
|
||||
return @as(PackedU64, @bitCast(x));
|
||||
return @bitCast(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2714,7 +2714,7 @@ pub const Float64 = struct {
|
||||
|
||||
pub fn get(self: Float64) f64 {
|
||||
const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32);
|
||||
return @as(f64, @bitCast(int_bits));
|
||||
return @bitCast(int_bits);
|
||||
}
|
||||
|
||||
fn pack(val: f64) Float64 {
|
||||
@ -2736,7 +2736,7 @@ pub const Float80 = struct {
|
||||
const int_bits = @as(u80, self.piece0) |
|
||||
(@as(u80, self.piece1) << 32) |
|
||||
(@as(u80, self.piece2) << 64);
|
||||
return @as(f80, @bitCast(int_bits));
|
||||
return @bitCast(int_bits);
|
||||
}
|
||||
|
||||
fn pack(val: f80) Float80 {
|
||||
@ -2761,7 +2761,7 @@ pub const Float128 = struct {
|
||||
(@as(u128, self.piece1) << 32) |
|
||||
(@as(u128, self.piece2) << 64) |
|
||||
(@as(u128, self.piece3) << 96);
|
||||
return @as(f128, @bitCast(int_bits));
|
||||
return @bitCast(int_bits);
|
||||
}
|
||||
|
||||
fn pack(val: f128) Float128 {
|
||||
@ -2968,16 +2968,18 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
|
||||
|
||||
.type_enum_auto => {
|
||||
const enum_auto = ip.extraDataTrail(EnumAuto, data);
|
||||
const names = @as(
|
||||
[]const NullTerminatedString,
|
||||
@ptrCast(ip.extra.items[enum_auto.end..][0..enum_auto.data.fields_len]),
|
||||
);
|
||||
return .{ .enum_type = .{
|
||||
.decl = enum_auto.data.decl,
|
||||
.namespace = enum_auto.data.namespace,
|
||||
.tag_ty = enum_auto.data.int_tag_type,
|
||||
.names = names,
|
||||
.values = &.{},
|
||||
.names = .{
|
||||
.start = @intCast(enum_auto.end),
|
||||
.len = enum_auto.data.fields_len,
|
||||
},
|
||||
.values = .{
|
||||
.start = 0,
|
||||
.len = 0,
|
||||
},
|
||||
.tag_mode = .auto,
|
||||
.names_map = enum_auto.data.names_map.toOptional(),
|
||||
.values_map = .none,
|
||||
@ -3443,21 +3445,19 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
|
||||
|
||||
fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
|
||||
const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
|
||||
const names = @as(
|
||||
[]const NullTerminatedString,
|
||||
@ptrCast(ip.extra.items[enum_explicit.end..][0..enum_explicit.data.fields_len]),
|
||||
);
|
||||
const values = if (enum_explicit.data.values_map != .none) @as(
|
||||
[]const Index,
|
||||
@ptrCast(ip.extra.items[enum_explicit.end + names.len ..][0..enum_explicit.data.fields_len]),
|
||||
) else &[0]Index{};
|
||||
|
||||
const fields_len = enum_explicit.data.fields_len;
|
||||
return .{ .enum_type = .{
|
||||
.decl = enum_explicit.data.decl,
|
||||
.namespace = enum_explicit.data.namespace,
|
||||
.tag_ty = enum_explicit.data.int_tag_type,
|
||||
.names = names,
|
||||
.values = values,
|
||||
.names = .{
|
||||
.start = @intCast(enum_explicit.end),
|
||||
.len = fields_len,
|
||||
},
|
||||
.values = .{
|
||||
.start = @intCast(enum_explicit.end + fields_len),
|
||||
.len = if (enum_explicit.data.values_map != .none) fields_len else 0,
|
||||
},
|
||||
.tag_mode = tag_mode,
|
||||
.names_map = enum_explicit.data.names_map.toOptional(),
|
||||
.values_map = enum_explicit.data.values_map,
|
||||
@ -3506,7 +3506,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.tag = .type_slice,
|
||||
.data = @intFromEnum(ptr_type_index),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
var ptr_type_adjusted = ptr_type;
|
||||
@ -3530,7 +3530,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.child = array_type.child,
|
||||
}),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3643,7 +3643,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
assert(anon_struct_type.types.len == anon_struct_type.values.len);
|
||||
for (anon_struct_type.types) |elem| assert(elem != .none);
|
||||
|
||||
const fields_len = @as(u32, @intCast(anon_struct_type.types.len));
|
||||
const fields_len: u32 = @intCast(anon_struct_type.types.len);
|
||||
if (anon_struct_type.names.len == 0) {
|
||||
try ip.extra.ensureUnusedCapacity(
|
||||
gpa,
|
||||
@ -3655,9 +3655,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.fields_len = fields_len,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.types)));
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.values)));
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
assert(anon_struct_type.names.len == anon_struct_type.types.len);
|
||||
@ -3672,10 +3672,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.fields_len = fields_len,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.types)));
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.values)));
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.names)));
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.names));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
},
|
||||
|
||||
.union_type => |union_type| {
|
||||
@ -3696,38 +3696,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
});
|
||||
},
|
||||
|
||||
.enum_type => |enum_type| {
|
||||
assert(enum_type.tag_ty == .noreturn_type or ip.isIntegerType(enum_type.tag_ty));
|
||||
for (enum_type.values) |value| assert(ip.typeOf(value) == enum_type.tag_ty);
|
||||
assert(enum_type.names_map == .none);
|
||||
assert(enum_type.values_map == .none);
|
||||
|
||||
switch (enum_type.tag_mode) {
|
||||
.auto => {
|
||||
const names_map = try ip.addMap(gpa);
|
||||
try addStringsToMap(ip, gpa, names_map, enum_type.names);
|
||||
|
||||
const fields_len = @as(u32, @intCast(enum_type.names.len));
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
|
||||
fields_len);
|
||||
ip.items.appendAssumeCapacity(.{
|
||||
.tag = .type_enum_auto,
|
||||
.data = ip.addExtraAssumeCapacity(EnumAuto{
|
||||
.decl = enum_type.decl,
|
||||
.namespace = enum_type.namespace,
|
||||
.int_tag_type = enum_type.tag_ty,
|
||||
.names_map = names_map,
|
||||
.fields_len = fields_len,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.names)));
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
},
|
||||
.explicit => return finishGetEnum(ip, gpa, enum_type, .type_enum_explicit),
|
||||
.nonexhaustive => return finishGetEnum(ip, gpa, enum_type, .type_enum_nonexhaustive),
|
||||
}
|
||||
},
|
||||
|
||||
.enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead
|
||||
.func_type => unreachable, // use getFuncType() instead
|
||||
.extern_func => unreachable, // use getExternFunc() instead
|
||||
.func => unreachable, // use getFuncInstance() or getFuncDecl() instead
|
||||
@ -3915,7 +3884,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.lazy_ty = lazy_ty,
|
||||
}),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
},
|
||||
}
|
||||
switch (int.ty) {
|
||||
@ -4056,7 +4025,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.value = casted,
|
||||
}),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
} else |_| {}
|
||||
|
||||
const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
|
||||
@ -4071,7 +4040,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.value = casted,
|
||||
}),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
var buf: [2]Limb = undefined;
|
||||
@ -4234,7 +4203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.tag = .only_possible_value,
|
||||
.data = @intFromEnum(aggregate.ty),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
switch (ty_key) {
|
||||
@ -4262,7 +4231,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.tag = .only_possible_value,
|
||||
.data = @intFromEnum(aggregate.ty),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@ -4301,7 +4270,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.elem_val = elem,
|
||||
}),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
if (child == .u8_type) bytes: {
|
||||
@ -4345,7 +4314,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.bytes = string,
|
||||
}),
|
||||
});
|
||||
return @as(Index, @enumFromInt(ip.items.len - 1));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
try ip.extra.ensureUnusedCapacity(
|
||||
@ -4358,7 +4327,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.ty = aggregate.ty,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(aggregate.storage.elems)));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(aggregate.storage.elems));
|
||||
if (sentinel != .none) ip.extra.appendAssumeCapacity(@intFromEnum(sentinel));
|
||||
},
|
||||
|
||||
@ -4384,7 +4353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.result = memoized_call.result,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values)));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(memoized_call.arg_values));
|
||||
},
|
||||
}
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
@ -5017,7 +4986,7 @@ pub const IncompleteEnumType = struct {
|
||||
.strings = @as([]const NullTerminatedString, @ptrCast(strings)),
|
||||
};
|
||||
const gop = try map.getOrPutAdapted(gpa, name, adapter);
|
||||
if (gop.found_existing) return @as(u32, @intCast(gop.index));
|
||||
if (gop.found_existing) return @intCast(gop.index);
|
||||
ip.extra.items[self.names_start + field_index] = @intFromEnum(name);
|
||||
return null;
|
||||
}
|
||||
@ -5038,7 +5007,7 @@ pub const IncompleteEnumType = struct {
|
||||
.indexes = @as([]const Index, @ptrCast(indexes)),
|
||||
};
|
||||
const gop = try map.getOrPutAdapted(gpa, value, adapter);
|
||||
if (gop.found_existing) return @as(u32, @intCast(gop.index));
|
||||
if (gop.found_existing) return @intCast(gop.index);
|
||||
ip.extra.items[self.values_start + field_index] = @intFromEnum(value);
|
||||
return null;
|
||||
}
|
||||
@ -5158,36 +5127,94 @@ fn getIncompleteEnumExplicit(
|
||||
};
|
||||
}
|
||||
|
||||
pub const GetEnumInit = struct {
|
||||
decl: Module.Decl.Index,
|
||||
namespace: Module.Namespace.OptionalIndex,
|
||||
tag_ty: Index,
|
||||
names: []const NullTerminatedString,
|
||||
values: []const Index,
|
||||
tag_mode: Key.EnumType.TagMode,
|
||||
};
|
||||
|
||||
pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {
|
||||
const adapter: KeyAdapter = .{ .intern_pool = ip };
|
||||
const gop = try ip.map.getOrPutAdapted(gpa, Key{
|
||||
.enum_type = .{
|
||||
// Only the decl is used for hashing and equality.
|
||||
.decl = ini.decl,
|
||||
|
||||
.namespace = undefined,
|
||||
.tag_ty = undefined,
|
||||
.names = undefined,
|
||||
.values = undefined,
|
||||
.tag_mode = undefined,
|
||||
.names_map = undefined,
|
||||
.values_map = undefined,
|
||||
},
|
||||
}, adapter);
|
||||
if (gop.found_existing) return @enumFromInt(gop.index);
|
||||
errdefer _ = ip.map.pop();
|
||||
try ip.items.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
assert(ini.tag_ty == .noreturn_type or ip.isIntegerType(ini.tag_ty));
|
||||
for (ini.values) |value| assert(ip.typeOf(value) == ini.tag_ty);
|
||||
|
||||
switch (ini.tag_mode) {
|
||||
.auto => {
|
||||
const names_map = try ip.addMap(gpa);
|
||||
try addStringsToMap(ip, gpa, names_map, ini.names);
|
||||
|
||||
const fields_len: u32 = @intCast(ini.names.len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
|
||||
fields_len);
|
||||
ip.items.appendAssumeCapacity(.{
|
||||
.tag = .type_enum_auto,
|
||||
.data = ip.addExtraAssumeCapacity(EnumAuto{
|
||||
.decl = ini.decl,
|
||||
.namespace = ini.namespace,
|
||||
.int_tag_type = ini.tag_ty,
|
||||
.names_map = names_map,
|
||||
.fields_len = fields_len,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
},
|
||||
.explicit => return finishGetEnum(ip, gpa, ini, .type_enum_explicit),
|
||||
.nonexhaustive => return finishGetEnum(ip, gpa, ini, .type_enum_nonexhaustive),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finishGetEnum(
|
||||
ip: *InternPool,
|
||||
gpa: Allocator,
|
||||
enum_type: Key.EnumType,
|
||||
ini: GetEnumInit,
|
||||
tag: Tag,
|
||||
) Allocator.Error!Index {
|
||||
const names_map = try ip.addMap(gpa);
|
||||
try addStringsToMap(ip, gpa, names_map, enum_type.names);
|
||||
try addStringsToMap(ip, gpa, names_map, ini.names);
|
||||
|
||||
const values_map: OptionalMapIndex = if (enum_type.values.len == 0) .none else m: {
|
||||
const values_map: OptionalMapIndex = if (ini.values.len == 0) .none else m: {
|
||||
const values_map = try ip.addMap(gpa);
|
||||
try addIndexesToMap(ip, gpa, values_map, enum_type.values);
|
||||
try addIndexesToMap(ip, gpa, values_map, ini.values);
|
||||
break :m values_map.toOptional();
|
||||
};
|
||||
const fields_len = @as(u32, @intCast(enum_type.names.len));
|
||||
const fields_len: u32 = @intCast(ini.names.len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +
|
||||
fields_len);
|
||||
ip.items.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = ip.addExtraAssumeCapacity(EnumExplicit{
|
||||
.decl = enum_type.decl,
|
||||
.namespace = enum_type.namespace,
|
||||
.int_tag_type = enum_type.tag_ty,
|
||||
.decl = ini.decl,
|
||||
.namespace = ini.namespace,
|
||||
.int_tag_type = ini.tag_ty,
|
||||
.fields_len = fields_len,
|
||||
.names_map = names_map,
|
||||
.values_map = values_map,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
@ -5486,7 +5513,7 @@ pub fn slicePtrType(ip: *const InternPool, i: Index) Index {
|
||||
}
|
||||
const item = ip.items.get(@intFromEnum(i));
|
||||
switch (item.tag) {
|
||||
.type_slice => return @as(Index, @enumFromInt(item.data)),
|
||||
.type_slice => return @enumFromInt(item.data),
|
||||
else => unreachable, // not a slice type
|
||||
}
|
||||
}
|
||||
@ -5618,7 +5645,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
|
||||
return ip.get(gpa, .{ .enum_tag = .{
|
||||
.ty = new_ty,
|
||||
.int = if (enum_type.values.len != 0)
|
||||
enum_type.values[index]
|
||||
enum_type.values.get(ip)[index]
|
||||
else
|
||||
try ip.get(gpa, .{ .int = .{
|
||||
.ty = enum_type.tag_ty,
|
||||
@ -6362,7 +6389,7 @@ pub fn createStruct(
|
||||
}
|
||||
const ptr = try ip.allocated_structs.addOne(gpa);
|
||||
ptr.* = initialization;
|
||||
return @as(Module.Struct.Index, @enumFromInt(ip.allocated_structs.len - 1));
|
||||
return @enumFromInt(ip.allocated_structs.len - 1);
|
||||
}
|
||||
|
||||
pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void {
|
||||
@ -6384,7 +6411,7 @@ pub fn createUnion(
|
||||
}
|
||||
const ptr = try ip.allocated_unions.addOne(gpa);
|
||||
ptr.* = initialization;
|
||||
return @as(Module.Union.Index, @enumFromInt(ip.allocated_unions.len - 1));
|
||||
return @enumFromInt(ip.allocated_unions.len - 1);
|
||||
}
|
||||
|
||||
pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) void {
|
||||
@ -6406,7 +6433,7 @@ pub fn createDecl(
|
||||
}
|
||||
const ptr = try ip.allocated_decls.addOne(gpa);
|
||||
ptr.* = initialization;
|
||||
return @as(Module.Decl.Index, @enumFromInt(ip.allocated_decls.len - 1));
|
||||
return @enumFromInt(ip.allocated_decls.len - 1);
|
||||
}
|
||||
|
||||
pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void {
|
||||
@ -6428,7 +6455,7 @@ pub fn createNamespace(
|
||||
}
|
||||
const ptr = try ip.allocated_namespaces.addOne(gpa);
|
||||
ptr.* = initialization;
|
||||
return @as(Module.Namespace.Index, @enumFromInt(ip.allocated_namespaces.len - 1));
|
||||
return @enumFromInt(ip.allocated_namespaces.len - 1);
|
||||
}
|
||||
|
||||
pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void {
|
||||
@ -6495,11 +6522,11 @@ pub fn getOrPutTrailingString(
|
||||
});
|
||||
if (gop.found_existing) {
|
||||
string_bytes.shrinkRetainingCapacity(str_index);
|
||||
return @as(NullTerminatedString, @enumFromInt(gop.key_ptr.*));
|
||||
return @enumFromInt(gop.key_ptr.*);
|
||||
} else {
|
||||
gop.key_ptr.* = str_index;
|
||||
string_bytes.appendAssumeCapacity(0);
|
||||
return @as(NullTerminatedString, @enumFromInt(str_index));
|
||||
return @enumFromInt(str_index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6725,7 +6752,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
|
||||
/// Assumes that the enum's field indexes equal its value tags.
|
||||
pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
|
||||
const int = ip.indexToKey(i).enum_tag.int;
|
||||
return @as(E, @enumFromInt(ip.indexToKey(int).int.storage.u64));
|
||||
return @enumFromInt(ip.indexToKey(int).int.storage.u64);
|
||||
}
|
||||
|
||||
pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
|
||||
@ -6758,9 +6785,9 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
|
||||
else => unreachable,
|
||||
};
|
||||
assert(child_item.tag == .type_function);
|
||||
return @as(Index, @enumFromInt(ip.extra.items[
|
||||
return @enumFromInt(ip.extra.items[
|
||||
child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
|
||||
]));
|
||||
]);
|
||||
}
|
||||
|
||||
pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
|
||||
@ -6791,9 +6818,9 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd
|
||||
switch (ip.items.items(.tag)[base]) {
|
||||
inline .ptr_decl,
|
||||
.ptr_mut_decl,
|
||||
=> |tag| return @as(Module.Decl.OptionalIndex, @enumFromInt(ip.extra.items[
|
||||
=> |tag| return @enumFromInt(ip.extra.items[
|
||||
ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "decl").?
|
||||
])),
|
||||
]),
|
||||
inline .ptr_eu_payload,
|
||||
.ptr_opt_payload,
|
||||
.ptr_elem,
|
||||
|
||||
@ -6655,7 +6655,7 @@ pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.E
|
||||
|
||||
return (try ip.get(gpa, .{ .enum_tag = .{
|
||||
.ty = ty.toIntern(),
|
||||
.int = enum_type.values[field_index],
|
||||
.int = enum_type.values.get(ip)[field_index],
|
||||
} })).toValue();
|
||||
}
|
||||
|
||||
|
||||
31
src/Sema.zig
31
src/Sema.zig
@ -17170,14 +17170,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
for (enum_field_vals, 0..) |*field_val, i| {
|
||||
const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
|
||||
const value_val = if (enum_type.values.len > 0)
|
||||
try mod.intern_pool.getCoerced(gpa, enum_type.values[i], .comptime_int_type)
|
||||
try mod.intern_pool.getCoerced(gpa, enum_type.values.get(ip)[i], .comptime_int_type)
|
||||
else
|
||||
try mod.intern(.{ .int = .{
|
||||
.ty = .comptime_int_type,
|
||||
.storage = .{ .u64 = @as(u64, @intCast(i)) },
|
||||
} });
|
||||
// TODO: write something like getCoercedInts to avoid needing to dupe
|
||||
const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names[i]));
|
||||
const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names.get(ip)[i]));
|
||||
const name_val = v: {
|
||||
var anon_decl = try block.startAnonDecl();
|
||||
defer anon_decl.deinit();
|
||||
@ -20601,7 +20601,7 @@ fn zirReify(
|
||||
errdefer msg.destroy(gpa);
|
||||
|
||||
const enum_ty = union_obj.tag_ty;
|
||||
for (tag_info.names, 0..) |field_name, field_index| {
|
||||
for (tag_info.names.get(ip), 0..) |field_name, field_index| {
|
||||
if (explicit_tags_seen[field_index]) continue;
|
||||
try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
|
||||
field_name.fmt(ip),
|
||||
@ -35420,7 +35420,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
const enum_ty = union_obj.tag_ty;
|
||||
for (tag_info.names, 0..) |field_name, field_index| {
|
||||
for (tag_info.names.get(ip), 0..) |field_name, field_index| {
|
||||
if (explicit_tags_seen[field_index]) continue;
|
||||
try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
|
||||
field_name.fmt(ip),
|
||||
@ -35452,12 +35452,13 @@ fn generateUnionTagTypeNumbered(
|
||||
) !Type {
|
||||
const mod = sema.mod;
|
||||
const gpa = sema.gpa;
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
const src_decl = mod.declPtr(block.src_decl);
|
||||
const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
|
||||
errdefer mod.destroyDecl(new_decl_index);
|
||||
const fqn = try union_obj.getFullyQualifiedName(mod);
|
||||
const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
|
||||
const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
|
||||
try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
|
||||
.ty = Type.noreturn,
|
||||
.val = Value.@"unreachable",
|
||||
@ -35469,17 +35470,17 @@ fn generateUnionTagTypeNumbered(
|
||||
new_decl.owns_tv = true;
|
||||
new_decl.name_fully_qualified = true;
|
||||
|
||||
const enum_ty = try mod.intern(.{ .enum_type = .{
|
||||
const enum_ty = try ip.getEnum(gpa, .{
|
||||
.decl = new_decl_index,
|
||||
.namespace = .none,
|
||||
.tag_ty = if (enum_field_vals.len == 0)
|
||||
(try mod.intType(.unsigned, 0)).toIntern()
|
||||
else
|
||||
mod.intern_pool.typeOf(enum_field_vals[0]),
|
||||
ip.typeOf(enum_field_vals[0]),
|
||||
.names = enum_field_names,
|
||||
.values = enum_field_vals,
|
||||
.tag_mode = .explicit,
|
||||
} });
|
||||
});
|
||||
|
||||
new_decl.ty = Type.type;
|
||||
new_decl.val = enum_ty.toValue();
|
||||
@ -35495,6 +35496,7 @@ fn generateUnionTagTypeSimple(
|
||||
maybe_union_obj: ?*Module.Union,
|
||||
) !Type {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
const gpa = sema.gpa;
|
||||
|
||||
const new_decl_index = new_decl_index: {
|
||||
@ -35508,7 +35510,7 @@ fn generateUnionTagTypeSimple(
|
||||
const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
|
||||
errdefer mod.destroyDecl(new_decl_index);
|
||||
const fqn = try union_obj.getFullyQualifiedName(mod);
|
||||
const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
|
||||
const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
|
||||
try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
|
||||
.ty = Type.noreturn,
|
||||
.val = Value.@"unreachable",
|
||||
@ -35518,7 +35520,7 @@ fn generateUnionTagTypeSimple(
|
||||
};
|
||||
errdefer mod.abortAnonDecl(new_decl_index);
|
||||
|
||||
const enum_ty = try mod.intern(.{ .enum_type = .{
|
||||
const enum_ty = try ip.getEnum(gpa, .{
|
||||
.decl = new_decl_index,
|
||||
.namespace = .none,
|
||||
.tag_ty = if (enum_field_names.len == 0)
|
||||
@ -35528,7 +35530,7 @@ fn generateUnionTagTypeSimple(
|
||||
.names = enum_field_names,
|
||||
.values = &.{},
|
||||
.tag_mode = .auto,
|
||||
} });
|
||||
});
|
||||
|
||||
const new_decl = mod.declPtr(new_decl_index);
|
||||
new_decl.owns_tv = true;
|
||||
@ -35625,6 +35627,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
|
||||
/// TODO assert the return value matches `ty.onePossibleValue`
|
||||
pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
return switch (ty.toIntern()) {
|
||||
.u0_type,
|
||||
.i0_type,
|
||||
@ -35718,7 +35721,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
.none,
|
||||
=> unreachable,
|
||||
|
||||
_ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
|
||||
_ => switch (ip.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
|
||||
.type_int_signed, // i0 handled above
|
||||
.type_int_unsigned, // u0 handled above
|
||||
.type_pointer,
|
||||
@ -35801,7 +35804,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
.type_union_tagged,
|
||||
.type_union_untagged,
|
||||
.type_union_safety,
|
||||
=> switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
=> switch (ip.indexToKey(ty.toIntern())) {
|
||||
inline .array_type, .vector_type => |seq_type, seq_tag| {
|
||||
const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
|
||||
if (seq_type.len + @intFromBool(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
|
||||
@ -35930,7 +35933,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
.storage = .{ .u64 = 0 },
|
||||
} })
|
||||
else
|
||||
enum_type.values[0]).toValue(), ty),
|
||||
enum_type.values.get(ip)[0]).toValue(), ty),
|
||||
else => return null,
|
||||
}
|
||||
},
|
||||
|
||||
@ -238,7 +238,7 @@ pub fn print(
|
||||
}
|
||||
const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
|
||||
if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
|
||||
try writer.print(".{i}", .{enum_type.names[tag_index].fmt(ip)});
|
||||
try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
|
||||
return;
|
||||
}
|
||||
try writer.writeAll("@enumFromInt(");
|
||||
|
||||
@ -1909,12 +1909,12 @@ pub const Object = struct {
|
||||
const int_info = ty.intInfo(mod);
|
||||
assert(int_info.bits != 0);
|
||||
|
||||
for (enum_type.names, 0..) |field_name_ip, i| {
|
||||
for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
|
||||
const field_name_z = ip.stringToSlice(field_name_ip);
|
||||
|
||||
var bigint_space: Value.BigIntSpace = undefined;
|
||||
const bigint = if (enum_type.values.len != 0)
|
||||
enum_type.values[i].toValue().toBigInt(&bigint_space, mod)
|
||||
enum_type.values.get(ip)[i].toValue().toBigInt(&bigint_space, mod)
|
||||
else
|
||||
std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
|
||||
|
||||
@ -9206,7 +9206,8 @@ pub const FuncGen = struct {
|
||||
fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
|
||||
const o = self.dg.object;
|
||||
const mod = o.module;
|
||||
const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
|
||||
const ip = &mod.intern_pool;
|
||||
const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
|
||||
|
||||
// TODO: detect when the type changes and re-emit this function.
|
||||
const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
|
||||
@ -9218,7 +9219,7 @@ pub const FuncGen = struct {
|
||||
const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
|
||||
try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),
|
||||
try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
|
||||
toLlvmAddressSpace(.generic, mod.getTarget()),
|
||||
);
|
||||
|
||||
@ -9241,8 +9242,8 @@ pub const FuncGen = struct {
|
||||
try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
|
||||
defer wip_switch.finish(&wip);
|
||||
|
||||
for (enum_type.names, 0..) |name, field_index| {
|
||||
const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
|
||||
for (enum_type.names.get(ip), 0..) |name, field_index| {
|
||||
const name_string = try o.builder.string(ip.stringToSlice(name));
|
||||
const name_init = try o.builder.stringNullConst(name_string);
|
||||
const name_variable_index =
|
||||
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
|
||||
|
||||
@ -388,9 +388,10 @@ pub const DeclState = struct {
|
||||
try ty.print(dbg_info_buffer.writer(), mod);
|
||||
try dbg_info_buffer.append(0);
|
||||
|
||||
const enum_type = mod.intern_pool.indexToKey(ty.ip_index).enum_type;
|
||||
for (enum_type.names, 0..) |field_name_index, field_i| {
|
||||
const field_name = mod.intern_pool.stringToSlice(field_name_index);
|
||||
const ip = &mod.intern_pool;
|
||||
const enum_type = ip.indexToKey(ty.ip_index).enum_type;
|
||||
for (enum_type.names.get(ip), 0..) |field_name_index, field_i| {
|
||||
const field_name = ip.stringToSlice(field_name_index);
|
||||
// DW.AT.enumerator
|
||||
try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
|
||||
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));
|
||||
@ -400,7 +401,7 @@ pub const DeclState = struct {
|
||||
// DW.AT.const_value, DW.FORM.data8
|
||||
const value: u64 = value: {
|
||||
if (enum_type.values.len == 0) break :value field_i; // auto-numbered
|
||||
const value = enum_type.values[field_i];
|
||||
const value = enum_type.values.get(ip)[field_i];
|
||||
// TODO do not assume a 64bit enum value - could be bigger.
|
||||
// See https://github.com/ziglang/zig/issues/645
|
||||
const field_int_val = try value.toValue().intFromEnum(ty, mod);
|
||||
|
||||
12
src/type.zig
12
src/type.zig
@ -2434,11 +2434,11 @@ pub const Type = struct {
|
||||
/// resolves field types rather than asserting they are already resolved.
|
||||
pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
|
||||
var ty = starting_type;
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
while (true) switch (ty.toIntern()) {
|
||||
.empty_struct_type => return Value.empty_struct,
|
||||
|
||||
else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
else => switch (ip.indexToKey(ty.toIntern())) {
|
||||
.int_type => |int_type| {
|
||||
if (int_type.bits == 0) {
|
||||
return try mod.intValue(ty, 0);
|
||||
@ -2619,7 +2619,7 @@ pub const Type = struct {
|
||||
} });
|
||||
return only.toValue();
|
||||
} else {
|
||||
return enum_type.values[0].toValue();
|
||||
return enum_type.values.get(ip)[0].toValue();
|
||||
}
|
||||
},
|
||||
else => return null,
|
||||
@ -2967,7 +2967,8 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
|
||||
return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
|
||||
const ip = &mod.intern_pool;
|
||||
return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip);
|
||||
}
|
||||
|
||||
pub fn enumFieldCount(ty: Type, mod: *Module) usize {
|
||||
@ -2975,7 +2976,8 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
|
||||
return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names[field_index];
|
||||
const ip = &mod.intern_pool;
|
||||
return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip)[field_index];
|
||||
}
|
||||
|
||||
pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
|
||||
|
||||
@ -426,7 +426,7 @@ pub const Value = struct {
|
||||
// Assume it is already an integer and return it directly.
|
||||
.simple_type, .int_type => val,
|
||||
.enum_type => |enum_type| if (enum_type.values.len != 0)
|
||||
enum_type.values[field_index].toValue()
|
||||
enum_type.values.get(ip)[field_index].toValue()
|
||||
else // Field index and integer values are the same.
|
||||
mod.intValue(enum_type.tag_ty.toType(), field_index),
|
||||
else => unreachable,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user