Ensure vtable entries for generics are attached constants (#5853)

Otherwise these end up as unattached constants (see the baseline test
changes) and can't be resolved by `GetConstantValueInSpecific` in
lowering or in further derived vtables.

If the class is non-generic, then it's fine for the vtable entry for
some function inherited from a generic base is represented as an
unattached constant, since the specific in that specific_function is
already fully resolved.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
This commit is contained in:
David Blaikie
2025-07-28 21:06:57 +00:00
committed by GitHub
co-authored by Dana Jansens
parent 5de47962b0
commit 26ec78ec00
5 changed files with 465 additions and 5 deletions
+18 -1
View File
@@ -176,7 +176,8 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
// TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the
// elements of the top of `vtable_stack`.
for (auto base_vtable_entry_id : base_vtable_inst_block) {
auto [derived_vtable_entry_id, fn_id, specific_id] =
auto [derived_vtable_entry_id, derived_vtable_entry_const_id, fn_id,
specific_id] =
DecomposeVirtualFunction(context.sem_ir(), base_vtable_entry_id,
base_class_specific_id);
const auto& fn = context.sem_ir().functions().Get(fn_id);
@@ -201,6 +202,22 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
derived_vtable_entry_id = build_specific_function(*i);
override_fn.virtual_index = vtable.size();
CARBON_CHECK(override_fn.virtual_index == fn.virtual_index);
} else if (auto base_vtable_specific_function =
context.sem_ir().insts().TryGetAs<SemIR::SpecificFunction>(
derived_vtable_entry_id)) {
if (derived_vtable_entry_const_id.is_symbolic()) {
// Create a new instruction here that is otherwise identical to
// `derived_vtable_entry_id` but is dependent within the derived
// class. This ensures we can `GetConstantValueInSpecific` for it
// with the derived class's specific (when forming further derived
// classes, lowering the vtable, etc).
derived_vtable_entry_id = GetOrAddInst<SemIR::SpecificFunction>(
context, node_id,
{.type_id = GetSingletonType(
context, SemIR::SpecificFunctionType::TypeInstId),
.callee_id = base_vtable_specific_function->callee_id,
.specific_id = base_vtable_specific_function->specific_id});
}
}
vtable.push_back(derived_vtable_entry_id);
}