mirror of
https://github.com/ziglang/zig.git
synced 2026-02-16 14:28:57 +00:00
InternPool: add missing logic
This commit is contained in:
parent
9584feae5f
commit
be1b231206
@ -1517,6 +1517,8 @@ pub const Tag = enum(u8) {
|
||||
/// 0. name: NullTerminatedString for each names_len
|
||||
pub const ErrorSet = struct {
|
||||
names_len: u32,
|
||||
/// Maps error names to declaration index.
|
||||
names_map: MapIndex,
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
@ -2024,6 +2026,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
|
||||
const names = ip.extra.items[error_set.end..][0..names_len];
|
||||
return .{ .error_set_type = .{
|
||||
.names = @ptrCast([]const NullTerminatedString, names),
|
||||
.names_map = error_set.data.names_map.toOptional(),
|
||||
} };
|
||||
},
|
||||
.type_inferred_error_set => .{
|
||||
@ -2518,6 +2521,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
.tag = .type_error_set,
|
||||
.data = ip.addExtraAssumeCapacity(ErrorSet{
|
||||
.names_len = names_len,
|
||||
.names_map = names_map,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names));
|
||||
@ -3605,15 +3609,34 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
|
||||
/// * int <=> int
|
||||
/// * int <=> enum
|
||||
/// * ptr <=> ptr
|
||||
/// * null_value => opt
|
||||
/// * payload => opt
|
||||
pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
|
||||
if (ip.typeOf(val) == new_ty) return val;
|
||||
const old_ty = ip.typeOf(val);
|
||||
if (old_ty == new_ty) return val;
|
||||
switch (ip.indexToKey(val)) {
|
||||
.int => |int| switch (ip.indexToKey(new_ty)) {
|
||||
.simple_type => |simple_type| switch (simple_type) {
|
||||
.usize,
|
||||
.isize,
|
||||
.c_char,
|
||||
.c_short,
|
||||
.c_ushort,
|
||||
.c_int,
|
||||
.c_uint,
|
||||
.c_long,
|
||||
.c_ulong,
|
||||
.c_longlong,
|
||||
.c_ulonglong,
|
||||
=> return getCoercedInts(ip, gpa, int, new_ty),
|
||||
else => {},
|
||||
},
|
||||
.int_type => return getCoercedInts(ip, gpa, int, new_ty),
|
||||
.enum_type => return ip.get(gpa, .{ .enum_tag = .{
|
||||
.ty = new_ty,
|
||||
.int = val,
|
||||
} }),
|
||||
else => return getCoercedInts(ip, gpa, int, new_ty),
|
||||
else => {},
|
||||
},
|
||||
.enum_tag => |enum_tag| {
|
||||
// Assume new_ty is an integer type.
|
||||
@ -3624,10 +3647,24 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
|
||||
.ty = new_ty,
|
||||
.addr = ptr.addr,
|
||||
} }),
|
||||
else => unreachable,
|
||||
else => {},
|
||||
},
|
||||
else => unreachable,
|
||||
else => {},
|
||||
}
|
||||
switch (ip.indexToKey(new_ty)) {
|
||||
.opt_type => |child_ty| switch (val) {
|
||||
.null_value => return ip.get(gpa, .{ .opt = .{
|
||||
.ty = new_ty,
|
||||
.val = .none,
|
||||
} }),
|
||||
else => return ip.get(gpa, .{ .opt = .{
|
||||
.ty = new_ty,
|
||||
.val = try ip.getCoerced(gpa, val, child_ty),
|
||||
} }),
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/// Asserts `val` has an integer type.
|
||||
|
||||
19
src/Sema.zig
19
src/Sema.zig
@ -8480,13 +8480,10 @@ fn zirOptionalPayload(
|
||||
};
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, operand)) |val| {
|
||||
if (val.isNull(mod)) {
|
||||
return sema.fail(block, src, "unable to unwrap null", .{});
|
||||
}
|
||||
if (val.castTag(.opt_payload)) |payload| {
|
||||
return sema.addConstant(result_ty, payload.data);
|
||||
}
|
||||
return sema.addConstant(result_ty, val);
|
||||
return if (val.optionalValue(mod)) |payload|
|
||||
sema.addConstant(result_ty, payload)
|
||||
else
|
||||
sema.fail(block, src, "unable to unwrap null", .{});
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, null);
|
||||
@ -18929,7 +18926,7 @@ fn zirReify(
|
||||
if (ptr_size == .One or ptr_size == .C) {
|
||||
return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
|
||||
}
|
||||
const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;
|
||||
const sentinel_ptr_val = sentinel_val.optionalValue(mod).?;
|
||||
const ptr_ty = try Type.ptr(sema.arena, mod, .{
|
||||
.@"addrspace" = .generic,
|
||||
.pointee_type = elem_ty,
|
||||
@ -28807,7 +28804,11 @@ fn coerceCompatiblePtrs(
|
||||
return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
|
||||
}
|
||||
// The comptime Value representation is compatible with both types.
|
||||
return sema.addConstant(dest_ty, val);
|
||||
return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced(
|
||||
mod.gpa,
|
||||
try val.intern(inst_ty, mod),
|
||||
dest_ty.ip_index,
|
||||
)).toValue());
|
||||
}
|
||||
try sema.requireRuntimeBlock(block, inst_src, null);
|
||||
const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod);
|
||||
|
||||
@ -718,18 +718,25 @@ pub const Value = struct {
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
const enum_type = ip.indexToKey(ty.ip_index).enum_type;
|
||||
if (enum_type.values.len != 0) {
|
||||
return enum_type.values[field_index].toValue();
|
||||
} else {
|
||||
// Field index and integer values are the same.
|
||||
return mod.intValue(enum_type.tag_ty.toType(), field_index);
|
||||
}
|
||||
return switch (ip.indexToKey(ty.ip_index)) {
|
||||
// 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()
|
||||
else // Field index and integer values are the same.
|
||||
mod.intValue(enum_type.tag_ty.toType(), field_index),
|
||||
else => unreachable,
|
||||
};
|
||||
},
|
||||
else => {
|
||||
const enum_type = ip.indexToKey(ip.typeOf(val.ip_index)).enum_type;
|
||||
const int = try ip.getCoerced(mod.gpa, val.ip_index, enum_type.tag_ty);
|
||||
return int.toValue();
|
||||
else => return switch (ip.indexToKey(ip.typeOf(val.ip_index))) {
|
||||
// Assume it is already an integer and return it directly.
|
||||
.simple_type, .int_type => val,
|
||||
.enum_type => |enum_type| (try ip.getCoerced(
|
||||
mod.gpa,
|
||||
val.ip_index,
|
||||
enum_type.tag_ty,
|
||||
)).toValue(),
|
||||
else => unreachable,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -2906,7 +2913,7 @@ pub const Value = struct {
|
||||
inline .u64, .i64 => |x| x == 0,
|
||||
},
|
||||
.opt => |opt| opt.val == .none,
|
||||
else => unreachable,
|
||||
else => false,
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -2949,11 +2956,20 @@ pub const Value = struct {
|
||||
|
||||
/// Value of the optional, null if optional has no payload.
|
||||
pub fn optionalValue(val: Value, mod: *const Module) ?Value {
|
||||
if (val.isNull(mod)) return null;
|
||||
|
||||
// Valid for optional representation to be the direct value
|
||||
// and not use opt_payload.
|
||||
return if (val.castTag(.opt_payload)) |p| p.data else val;
|
||||
return switch (val.ip_index) {
|
||||
.none => if (val.isNull(mod)) null
|
||||
// Valid for optional representation to be the direct value
|
||||
// and not use opt_payload.
|
||||
else if (val.castTag(.opt_payload)) |p| p.data else val,
|
||||
.null_value => null,
|
||||
else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => null,
|
||||
else => opt.val.toValue(),
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// Valid for all types. Asserts the value is not undefined.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user