|
|
@@ -7,6 +7,7 @@
|
|
|
#include "toolchain/base/kind_switch.h"
|
|
|
#include "toolchain/check/context.h"
|
|
|
#include "toolchain/check/diagnostic_helpers.h"
|
|
|
+#include "toolchain/check/generic.h"
|
|
|
#include "toolchain/check/merge.h"
|
|
|
#include "toolchain/check/name_component.h"
|
|
|
#include "toolchain/diagnostics/diagnostic.h"
|
|
|
@@ -199,12 +200,13 @@ auto DeclNameStack::LookupOrAddName(NameContext name_context,
|
|
|
static auto PushNameQualifierScope(Context& context,
|
|
|
SemIR::InstId scope_inst_id,
|
|
|
SemIR::NameScopeId scope_id,
|
|
|
+ SemIR::GenericInstanceId instance_id,
|
|
|
bool has_error = false) -> void {
|
|
|
// If the qualifier has no parameters, we don't need to keep around a
|
|
|
// parameter scope.
|
|
|
context.scope_stack().PopIfEmpty();
|
|
|
|
|
|
- context.scope_stack().Push(scope_inst_id, scope_id, has_error);
|
|
|
+ context.scope_stack().Push(scope_inst_id, scope_id, instance_id, has_error);
|
|
|
|
|
|
// Enter a parameter scope in case the qualified name itself has parameters.
|
|
|
context.scope_stack().Push();
|
|
|
@@ -216,9 +218,10 @@ auto DeclNameStack::ApplyNameQualifier(const NameComponent& name) -> void {
|
|
|
name_context.has_qualifiers = true;
|
|
|
|
|
|
// Resolve the qualifier as a scope and enter the new scope.
|
|
|
- auto scope_id = ResolveAsScope(name_context, name);
|
|
|
+ auto [scope_id, instance_id] = ResolveAsScope(name_context, name);
|
|
|
if (scope_id.is_valid()) {
|
|
|
PushNameQualifierScope(*context_, name_context.resolved_inst_id, scope_id,
|
|
|
+ instance_id,
|
|
|
context_->name_scopes().Get(scope_id).has_error);
|
|
|
name_context.parent_scope_id = scope_id;
|
|
|
} else {
|
|
|
@@ -349,9 +352,13 @@ static auto DiagnoseQualifiedDeclInNonScope(Context& context, SemIRLoc use_loc,
|
|
|
|
|
|
auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
|
|
|
const NameComponent& name) const
|
|
|
- -> SemIR::NameScopeId {
|
|
|
+ -> std::pair<SemIR::NameScopeId, SemIR::GenericInstanceId> {
|
|
|
+ constexpr std::pair<SemIR::NameScopeId, SemIR::GenericInstanceId>
|
|
|
+ InvalidResult = {SemIR::NameScopeId::Invalid,
|
|
|
+ SemIR::GenericInstanceId::Invalid};
|
|
|
+
|
|
|
if (!CheckQualifierIsResolved(*context_, name_context)) {
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
|
|
|
auto new_params =
|
|
|
@@ -363,29 +370,31 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
|
|
|
const auto& class_info = context_->classes().Get(class_decl.class_id);
|
|
|
if (!CheckRedeclParamsMatch(*context_, new_params,
|
|
|
DeclParams(class_info))) {
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
if (!class_info.is_defined()) {
|
|
|
DiagnoseQualifiedDeclInIncompleteClassScope(
|
|
|
*context_, name_context.loc_id, class_decl.class_id);
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
- return class_info.scope_id;
|
|
|
+ return {class_info.scope_id,
|
|
|
+ context_->generics().GetSelfInstance(class_info.generic_id)};
|
|
|
}
|
|
|
case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
|
|
|
const auto& interface_info =
|
|
|
context_->interfaces().Get(interface_decl.interface_id);
|
|
|
if (!CheckRedeclParamsMatch(*context_, new_params,
|
|
|
DeclParams(interface_info))) {
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
if (!interface_info.is_defined()) {
|
|
|
DiagnoseQualifiedDeclInUndefinedInterfaceScope(
|
|
|
*context_, name_context.loc_id, interface_decl.interface_id,
|
|
|
name_context.resolved_inst_id);
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
- return interface_info.scope_id;
|
|
|
+ return {interface_info.scope_id,
|
|
|
+ context_->generics().GetSelfInstance(interface_info.generic_id)};
|
|
|
}
|
|
|
case CARBON_KIND(SemIR::Namespace resolved_inst): {
|
|
|
auto scope_id = resolved_inst.name_scope_id;
|
|
|
@@ -394,7 +403,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
|
|
|
DeclParams(name_context.resolved_inst_id,
|
|
|
SemIR::InstBlockId::Invalid,
|
|
|
SemIR::InstBlockId::Invalid))) {
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
if (scope.is_closed_import) {
|
|
|
DiagnoseQualifiedDeclInImportedPackage(*context_, name_context.loc_id,
|
|
|
@@ -403,12 +412,12 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
|
|
|
// be used as a name qualifier.
|
|
|
scope.is_closed_import = false;
|
|
|
}
|
|
|
- return scope_id;
|
|
|
+ return {scope_id, SemIR::GenericInstanceId::Invalid};
|
|
|
}
|
|
|
default: {
|
|
|
DiagnoseQualifiedDeclInNonScope(*context_, name_context.loc_id,
|
|
|
name_context.resolved_inst_id);
|
|
|
- return SemIR::NameScopeId::Invalid;
|
|
|
+ return InvalidResult;
|
|
|
}
|
|
|
}
|
|
|
}
|