InternPool: unwrap func_coerced when using it as generic_owner

This commit is contained in:
Andrew Kelley 2023-07-14 23:04:48 -07:00
parent 1b70fca534
commit 9f61c29bfb

View File

@ -4729,7 +4729,9 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
.addrspace_is_generic = false,
});
assert(arg.comptime_args.len == ip.funcTypeParamsLen(ip.typeOf(arg.generic_owner)));
const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);
assert(arg.comptime_args.len == ip.funcTypeParamsLen(ip.typeOf(generic_owner)));
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncInstance).Struct.fields.len +
arg.comptime_args.len);
@ -4750,7 +4752,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
.owner_decl = undefined,
.ty = func_ty,
.branch_quota = 0,
.generic_owner = arg.generic_owner,
.generic_owner = generic_owner,
});
ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args));
@ -4775,7 +4777,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
return finishFuncInstance(
ip,
gpa,
arg.generic_owner,
generic_owner,
func_index,
func_extra_index,
arg.generation,
@ -5673,7 +5675,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
} });
},
.elems => |elems| {
const elems_copy = try gpa.dupe(InternPool.Index, elems[0..new_len]);
const elems_copy = try gpa.dupe(Index, elems[0..new_len]);
defer gpa.free(elems_copy);
return ip.get(gpa, .{ .aggregate = .{
.ty = new_ty,
@ -5689,7 +5691,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
}
}
// Direct approach failed - we must recursively coerce elems
const agg_elems = try gpa.alloc(InternPool.Index, new_len);
const agg_elems = try gpa.alloc(Index, new_len);
defer gpa.free(agg_elems);
// First, fill the vector with the uncoerced elements. We do this to avoid key
// lifetime issues, since it'll allow us to avoid referencing `aggregate` after we
@ -6042,7 +6044,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
.type_function => b: {
const info = ip.extraData(Tag.TypeFunction, data);
break :b @sizeOf(Tag.TypeFunction) + (@sizeOf(Index) * info.params_len);
break :b @sizeOf(Tag.TypeFunction) +
(@sizeOf(Index) * info.params_len) +
(@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) +
(@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits));
},
.undef => 0,
@ -6996,7 +7001,7 @@ pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {
return ip.extra.items[extra_index];
}
pub fn iesFuncIndex(ip: *const InternPool, ies_index: InternPool.Index) InternPool.Index {
pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index {
assert(ies_index != .none);
const tags = ip.items.items(.tag);
assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set);
@ -7011,7 +7016,7 @@ pub fn iesFuncIndex(ip: *const InternPool, ies_index: InternPool.Index) InternPo
/// Returns a mutable pointer to the resolved error set type of an inferred
/// error set function. The returned pointer is invalidated when anything is
/// added to `ip`.
pub fn iesResolved(ip: *const InternPool, ies_index: InternPool.Index) *InternPool.Index {
pub fn iesResolved(ip: *const InternPool, ies_index: Index) *Index {
assert(ies_index != .none);
const tags = ip.items.items(.tag);
const datas = ip.items.items(.data);
@ -7023,7 +7028,7 @@ pub fn iesResolved(ip: *const InternPool, ies_index: InternPool.Index) *InternPo
/// Returns a mutable pointer to the resolved error set type of an inferred
/// error set function. The returned pointer is invalidated when anything is
/// added to `ip`.
pub fn funcIesResolved(ip: *const InternPool, func_index: InternPool.Index) *InternPool.Index {
pub fn funcIesResolved(ip: *const InternPool, func_index: Index) *Index {
const tags = ip.items.items(.tag);
const datas = ip.items.items(.data);
assert(funcHasInferredErrorSet(ip, func_index));
@ -7036,21 +7041,35 @@ pub fn funcIesResolved(ip: *const InternPool, func_index: InternPool.Index) *Int
return @ptrCast(&ip.extra.items[extra_index]);
}
pub fn funcDeclInfo(ip: *const InternPool, i: InternPool.Index) Key.Func {
pub fn funcDeclInfo(ip: *const InternPool, i: Index) Key.Func {
const tags = ip.items.items(.tag);
const datas = ip.items.items(.data);
assert(tags[@intFromEnum(i)] == .func_decl);
return extraFuncDecl(ip, datas[@intFromEnum(i)]);
}
pub fn funcDeclOwner(ip: *const InternPool, i: InternPool.Index) Module.Decl.Index {
pub fn funcDeclOwner(ip: *const InternPool, i: Index) Module.Decl.Index {
return funcDeclInfo(ip, i).owner_decl;
}
pub fn funcTypeParamsLen(ip: *const InternPool, i: InternPool.Index) u32 {
pub fn funcTypeParamsLen(ip: *const InternPool, i: Index) u32 {
const tags = ip.items.items(.tag);
const datas = ip.items.items(.data);
assert(tags[@intFromEnum(i)] == .type_function);
const start = datas[@intFromEnum(i)];
return ip.extra.items[start + std.meta.fieldIndex(Tag.TypeFunction, "params_len").?];
}
fn unwrapCoercedFunc(ip: *const InternPool, i: Index) Index {
const tags = ip.items.items(.tag);
return switch (tags[@intFromEnum(i)]) {
.func_coerced => {
const datas = ip.items.items(.data);
return @enumFromInt(ip.extra.items[
datas[@intFromEnum(i)] + std.meta.fieldIndex(Tag.FuncCoerced, "func").?
]);
},
.func_instance, .func_decl => i,
else => unreachable,
};
}