Support signature mismatch between virtual fn and override fn. (#7198)

For now, hide `override fn`s from name lookup, so that the base class
version is always used, as the derived-class version does not have its
own vptr entry and so would not do the right thing if a further-derived
class adds a new override. This is implemented via a new access kind of
`Hidden`.

When checking the overriding function, pass in the expected `Self` type
and check the `self` parameter against that; the signature that we
generate for the thunk in the derived class is the base class signature
with the `self` parameter's type changed to the derived class.

When we generate a thunk for a virtual function, the thunk is assigned a
`virtual_index`, and the virtual function itself is not. When the thunk
makes a direct call to the virtual function, recognize this situation by
checking for a `virtual_index`, and perform a non-virtual call if there
isn't one.

Assisted-by: Gemini via Antigravity
This commit is contained in:
Richard Smith
2026-05-13 17:40:45 +00:00
committed by GitHub
parent 0b47efa57a
commit c33fb9fc48
18 changed files with 427 additions and 110 deletions
+4 -4
View File
@@ -78,8 +78,9 @@ auto CheckAssociatedFunctionImplementation(
enclosing_specific_id);
return BuildThunk(context, interface_function_type.function_id,
interface_function_specific_id, impl_decl_id,
defer_thunk_definition);
interface_function_specific_id,
/*signature_self_type_override_id=*/SemIR::TypeId::None,
impl_decl_id, defer_thunk_definition);
}
static auto GetScopeInstId(Context& context, SemIR::InstId scope_inst_id)
@@ -160,8 +161,7 @@ static auto VerifyImplRedecl(Context& context, const SemIR::Impl& new_impl,
// `impl`. Keep looking for a prior declaration without issuing a diagnostic.
if (!CheckRedeclParamsMatch(context, DeclParams(new_impl),
DeclParams(prev_impl), SemIR::SpecificId::None,
/*diagnose=*/false, /*check_syntax=*/true,
/*check_self=*/true)) {
/*diagnose=*/false, /*check_syntax=*/true)) {
return ImplRedeclType::Mismatch;
}