Add an instruction to represent a use of a dependent value from a generic instance. (#4122)

We can't use the instruction from the generic directly, because it
doesn't have the right constant value. Instead add an instruction that
models the transition from the constant value in the generic to the
constant value in the generic instance.

Also start associating the self generic instance with unqualified
lookups that find results in an enclosing generic, so that we track the
information necessary to create the new instruction.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
Richard Smith
2024-07-12 14:59:01 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent 6d2d1cf7ca
commit 50d56aa7c9
30 changed files with 259 additions and 144 deletions
+22 -13
View File
@@ -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;
}
}
}