mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-01 22:02:45 +01:00
Support unqualified lookup into extended interfaces from classes and impls (#7217)
When a class extends an interface, referring to a member name of the interface as an unqualified name should refer to the class's corresponding associated entity value, not to the associated entity itself. Similarly, in an `impl`, unqualified names of associated entities should refer to the `impl`'s corresponding value for that entity. To support this, we treat `impl`s as `extend`ing their implemented facet type, and we make lookups into an extended facet type use the `Self` type of the extending `impl` or `class` if lookup finds an associated entity. We already did the latter if the extending entity was an interface; this extends the existing support for these other cases.
This commit is contained in:
@@ -184,9 +184,15 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id,
|
||||
SemIR::FunctionDecl& function_decl,
|
||||
SemIR::Function& function_info, bool is_definition)
|
||||
-> void {
|
||||
// Diagnose if we are declaring a poisoned name. However, don't diagnose at
|
||||
// impl scope: if the name was referenced before being declared, we will have
|
||||
// produced an error already.
|
||||
if (name_context.state == DeclNameStack::NameContext::State::Poisoned) {
|
||||
DiagnosePoisonedName(context, name_context.name_id_for_new_inst(),
|
||||
name_context.poisoning_loc_id, name_context.loc_id);
|
||||
if (!context.name_scopes().InstIs<SemIR::ImplDecl>(
|
||||
name_context.parent_scope_id)) {
|
||||
DiagnosePoisonedName(context, name_context.name_id_for_new_inst(),
|
||||
name_context.poisoning_loc_id, name_context.loc_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -200,8 +206,7 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id,
|
||||
auto prev_import_ir_id = SemIR::ImportIRId::None;
|
||||
CARBON_KIND_SWITCH(context.insts().Get(prev_id)) {
|
||||
case CARBON_KIND(SemIR::AssociatedEntity assoc_entity): {
|
||||
// This is a function in an interface definition scope (see
|
||||
// NameScope::is_interface_definition()).
|
||||
// This is a function in an interface definition scope.
|
||||
auto function_decl =
|
||||
context.insts().GetAs<SemIR::FunctionDecl>(assoc_entity.decl_id);
|
||||
prev_function_id = function_decl.function_id;
|
||||
@@ -260,7 +265,7 @@ static auto MaybeAddToNameLookup(Context& context,
|
||||
const KeywordModifierSet& modifier_set,
|
||||
SemIR::NameScopeId parent_scope_id,
|
||||
SemIR::InstId decl_id) -> void {
|
||||
if (name_context.state == DeclNameStack::NameContext::State::Poisoned ||
|
||||
if (name_context.state != DeclNameStack::NameContext::State::Poisoned &&
|
||||
name_context.prev_inst_id().has_value()) {
|
||||
return;
|
||||
}
|
||||
@@ -269,12 +274,11 @@ static auto MaybeAddToNameLookup(Context& context,
|
||||
// function.
|
||||
auto lookup_result_id = decl_id;
|
||||
if (parent_scope_id.has_value() && !name_context.has_qualifiers) {
|
||||
const auto& parent_scope = context.name_scopes().Get(parent_scope_id);
|
||||
if (parent_scope.is_interface_definition()) {
|
||||
auto interface_decl = context.insts().GetAs<SemIR::InterfaceWithSelfDecl>(
|
||||
parent_scope.inst_id());
|
||||
if (auto interface_decl =
|
||||
context.name_scopes().TryGetInstAs<SemIR::InterfaceWithSelfDecl>(
|
||||
parent_scope_id)) {
|
||||
lookup_result_id =
|
||||
BuildAssociatedEntity(context, interface_decl.interface_id, decl_id);
|
||||
BuildAssociatedEntity(context, interface_decl->interface_id, decl_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user