Rename "generic instance" to "specific" throughout the toolchain. (#4165)

As discussed in toolchain meeting, we want to avoid overloading the
meaning of "instance", and "specific" was the best name we found. It's a
little unorthodox and inventive, but hopefully over time will become as
unsurprising as the term "generic" is.
This commit is contained in:
Richard Smith
2024-07-25 16:42:01 +00:00
committed by GitHub
parent 70c20be91b
commit 3cb769a053
41 changed files with 370 additions and 396 deletions
+6 -6
View File
@@ -27,7 +27,7 @@ static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id,
// TODO: Pass in information about the specific in which the generic class
// name was found.
// TODO: Perform argument deduction.
auto specific_id = SemIR::GenericInstanceId::Invalid;
auto specific_id = SemIR::SpecificId::Invalid;
// Convert the arguments to match the parameters.
auto converted_args_id = ConvertCallArgs(
@@ -53,7 +53,7 @@ static auto PerformCallToGenericInterface(Context& context,
// TODO: Pass in information about the specific in which the generic interface
// name was found.
// TODO: Perform argument deduction.
auto specific_id = SemIR::GenericInstanceId::Invalid;
auto specific_id = SemIR::SpecificId::Invalid;
// Convert the arguments to match the parameters.
auto converted_args_id = ConvertCallArgs(
@@ -101,15 +101,15 @@ auto PerformCall(Context& context, Parse::NodeId node_id,
// TODO: Properly determine the generic argument values for the call. For now,
// we do so only if the function introduces no generic parameters beyond those
// of the enclosing context.
auto specific_id = SemIR::GenericInstanceId::Invalid;
if (callee_function.instance_id.is_valid()) {
auto specific_id = SemIR::SpecificId::Invalid;
if (callee_function.specific_id.is_valid()) {
auto enclosing_args_id =
context.generic_instances().Get(callee_function.instance_id).args_id;
context.specifics().Get(callee_function.specific_id).args_id;
auto fn_params_id = context.generics().Get(callable.generic_id).bindings_id;
if (context.inst_blocks().Get(fn_params_id).size() ==
context.inst_blocks().Get(enclosing_args_id).size()) {
specific_id =
MakeGenericInstance(context, callable.generic_id, enclosing_args_id);
MakeSpecific(context, callable.generic_id, enclosing_args_id);
}
}
+1 -2
View File
@@ -206,8 +206,7 @@ static auto ImportCurrentPackage(Context& context, UnitInfo& unit_info,
/*api_imports=*/nullptr, total_ir_count));
context.scope_stack().Push(
package_inst_id, SemIR::NameScopeId::Package,
SemIR::GenericInstanceId::Invalid,
package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::Invalid,
context.name_scopes().Get(SemIR::NameScopeId::Package).has_error);
}
+18 -19
View File
@@ -275,11 +275,11 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
scope_stack().LookupInLexicalScopes(name_id);
// Walk the non-lexical scopes and perform lookups into each of them.
for (auto [index, lookup_scope_id, instance_id] :
for (auto [index, lookup_scope_id, specific_id] :
llvm::reverse(non_lexical_scopes)) {
if (auto non_lexical_result = LookupQualifiedName(
node_id, name_id,
{.name_scope_id = lookup_scope_id, .instance_id = instance_id},
{.name_scope_id = lookup_scope_id, .specific_id = specific_id},
/*required=*/false);
non_lexical_result.inst_id.is_valid()) {
return non_lexical_result;
@@ -287,16 +287,16 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
}
if (lexical_result.is_valid()) {
// A lexical scope never needs an associated generic instance. If there's a
// A lexical scope never needs an associated specific. If there's a
// lexically enclosing generic, then it also encloses the point of use of
// the name.
return {.instance_id = SemIR::GenericInstanceId::Invalid,
return {.specific_id = SemIR::SpecificId::Invalid,
.inst_id = lexical_result};
}
// We didn't find anything at all.
DiagnoseNameNotFound(node_id, name_id);
return {.instance_id = SemIR::GenericInstanceId::Invalid,
return {.specific_id = SemIR::SpecificId::Invalid,
.inst_id = SemIR::InstId::BuiltinError};
}
@@ -320,13 +320,13 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
LookupScope scope, bool required)
-> LookupResult {
llvm::SmallVector<LookupScope> scopes = {scope};
LookupResult result = {.instance_id = SemIR::GenericInstanceId::Invalid,
LookupResult result = {.specific_id = SemIR::SpecificId::Invalid,
.inst_id = SemIR::InstId::Invalid};
bool has_error = false;
// Walk this scope and, if nothing is found here, the scopes it extends.
while (!scopes.empty()) {
auto [scope_id, instance_id] = scopes.pop_back_val();
auto [scope_id, specific_id] = scopes.pop_back_val();
const auto& name_scope = name_scopes().Get(scope_id);
has_error |= name_scope.has_error;
@@ -338,9 +338,9 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
scopes.reserve(scopes.size() + extended.size());
for (auto extended_id : llvm::reverse(extended)) {
// TODO: Track a constant describing the extended scope, and substitute
// into it to determine its corresponding generic instance.
// into it to determine its corresponding specific.
scopes.push_back({.name_scope_id = extended_id,
.instance_id = SemIR::GenericInstanceId::Invalid});
.specific_id = SemIR::SpecificId::Invalid});
}
continue;
}
@@ -356,19 +356,19 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
SemIR::NameId);
emitter_->Emit(node_id, NameAmbiguousDueToExtend, name_id);
// TODO: Add notes pointing to the scopes.
return {.instance_id = SemIR::GenericInstanceId::Invalid,
return {.specific_id = SemIR::SpecificId::Invalid,
.inst_id = SemIR::InstId::BuiltinError};
}
result.inst_id = scope_result_id;
result.instance_id = instance_id;
result.specific_id = specific_id;
}
if (required && !result.inst_id.is_valid()) {
if (!has_error) {
DiagnoseNameNotFound(node_id, name_id);
}
return {.instance_id = SemIR::GenericInstanceId::Invalid,
return {.specific_id = SemIR::SpecificId::Invalid,
.inst_id = SemIR::InstId::BuiltinError};
}
@@ -715,8 +715,8 @@ class TypeCompleter {
}
return false;
}
if (inst.instance_id.is_valid()) {
ResolveSpecificDefinition(context_, inst.instance_id);
if (inst.specific_id.is_valid()) {
ResolveSpecificDefinition(context_, inst.specific_id);
}
Push(class_info.object_repr_id);
break;
@@ -1012,8 +1012,8 @@ auto Context::TryToDefineType(
return false;
}
if (interface->instance_id.is_valid()) {
ResolveSpecificDefinition(*this, interface->instance_id);
if (interface->specific_id.is_valid()) {
ResolveSpecificDefinition(*this, interface->specific_id);
}
}
@@ -1085,9 +1085,8 @@ auto Context::GetBuiltinType(SemIR::BuiltinInstKind kind) -> SemIR::TypeId {
}
auto Context::GetFunctionType(SemIR::FunctionId fn_id,
SemIR::GenericInstanceId instance_id)
-> SemIR::TypeId {
return GetCompleteTypeImpl<SemIR::FunctionType>(*this, fn_id, instance_id);
SemIR::SpecificId specific_id) -> SemIR::TypeId {
return GetCompleteTypeImpl<SemIR::FunctionType>(*this, fn_id, specific_id);
}
auto Context::GetGenericClassType(SemIR::ClassId class_id) -> SemIR::TypeId {
+9 -11
View File
@@ -30,16 +30,16 @@ namespace Carbon::Check {
struct LookupScope {
// The name scope in which names are searched.
SemIR::NameScopeId name_scope_id;
// The generic instance for the name scope, or `Invalid` if the name scope is
// not an instance of a generic.
SemIR::GenericInstanceId instance_id;
// The specific for the name scope, or `Invalid` if the name scope is not
// defined by a generic or we should perform lookup into the generic itself.
SemIR::SpecificId specific_id;
};
// A result produced by name lookup.
struct LookupResult {
// The generic instance in which the lookup result was found. `Invalid` if the
// result was not found in a generic instance.
SemIR::GenericInstanceId instance_id;
// The specific in which the lookup result was found. `Invalid` if the result
// was not found in a specific.
SemIR::SpecificId specific_id;
// The declaration that was found by name lookup.
SemIR::InstId inst_id;
};
@@ -288,8 +288,8 @@ class Context {
auto GetBuiltinType(SemIR::BuiltinInstKind kind) -> SemIR::TypeId;
// Gets a function type. The returned type will be complete.
auto GetFunctionType(SemIR::FunctionId fn_id,
SemIR::GenericInstanceId instance_id) -> SemIR::TypeId;
auto GetFunctionType(SemIR::FunctionId fn_id, SemIR::SpecificId specific_id)
-> SemIR::TypeId;
// Gets a generic class type, which is the type of a name of a generic class,
// such as the type of `Vector` given `class Vector(T:! type)`. The returned
@@ -423,9 +423,7 @@ class Context {
}
auto impls() -> SemIR::ImplStore& { return sem_ir().impls(); }
auto generics() -> SemIR::GenericStore& { return sem_ir().generics(); }
auto generic_instances() -> SemIR::GenericInstanceStore& {
return sem_ir().generic_instances();
}
auto specifics() -> SemIR::SpecificStore& { return sem_ir().specifics(); }
auto import_irs() -> ValueStore<SemIR::ImportIRId>& {
return sem_ir().import_irs();
}
+4 -4
View File
@@ -1119,7 +1119,7 @@ CARBON_DIAGNOSTIC(InCallToFunction, Note, "Calling function declared here.");
// Convert the object argument in a method call to match the `self` parameter.
static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
SemIR::InstId callee_id,
SemIR::GenericInstanceId callee_specific_id,
SemIR::SpecificId callee_specific_id,
std::optional<SemIR::AddrPattern> addr_pattern,
SemIR::InstId self_param_id, SemIR::Param self_param,
SemIR::InstId self_id) -> SemIR::InstId {
@@ -1168,7 +1168,7 @@ static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
return ConvertToValueOfType(
context, call_loc_id, self_or_addr_id,
SemIR::GetTypeInInstance(context.sem_ir(), callee_specific_id,
SemIR::GetTypeInSpecific(context.sem_ir(), callee_specific_id,
self_param.type_id));
}
@@ -1177,7 +1177,7 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
llvm::ArrayRef<SemIR::InstId> arg_refs,
SemIR::InstId return_storage_id,
const SemIR::EntityWithParamsBase& callee,
SemIR::GenericInstanceId callee_specific_id)
SemIR::SpecificId callee_specific_id)
-> SemIR::InstBlockId {
auto implicit_param_refs =
context.inst_blocks().GetOrEmpty(callee.implicit_param_refs_id);
@@ -1238,7 +1238,7 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
diag_param_index = i;
auto param_type_id =
SemIR::GetTypeInInstance(context.sem_ir(), callee_specific_id,
SemIR::GetTypeInSpecific(context.sem_ir(), callee_specific_id,
context.insts().Get(param_id).type_id());
// TODO: Convert to the proper expression category. For now, we assume
// parameters are all `let` bindings.
+1 -1
View File
@@ -97,7 +97,7 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
llvm::ArrayRef<SemIR::InstId> arg_refs,
SemIR::InstId return_storage_id,
const SemIR::EntityWithParamsBase& callee,
SemIR::GenericInstanceId callee_specific_id)
SemIR::SpecificId callee_specific_id)
-> SemIR::InstBlockId;
// Converts an expression for use as a type.
+12 -13
View File
@@ -200,18 +200,18 @@ auto DeclNameStack::LookupOrAddName(NameContext name_context,
static auto PushNameQualifierScope(Context& context,
SemIR::InstId scope_inst_id,
SemIR::NameScopeId scope_id,
SemIR::GenericInstanceId instance_id,
SemIR::SpecificId specific_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();
// When declaring a member of a generic, resolve the self specific.
if (instance_id.is_valid()) {
ResolveSpecificDefinition(context, instance_id);
if (specific_id.is_valid()) {
ResolveSpecificDefinition(context, specific_id);
}
context.scope_stack().Push(scope_inst_id, scope_id, instance_id, has_error);
context.scope_stack().Push(scope_inst_id, scope_id, specific_id, has_error);
// An interface also introduces its 'Self' parameter into scope, despite it
// not being redeclared as part of the qualifier.
@@ -232,10 +232,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, instance_id] = ResolveAsScope(name_context, name);
auto [scope_id, specific_id] = ResolveAsScope(name_context, name);
if (scope_id.is_valid()) {
PushNameQualifierScope(*context_, name_context.resolved_inst_id, scope_id,
instance_id,
specific_id,
context_->name_scopes().Get(scope_id).has_error);
name_context.parent_scope_id = scope_id;
} else {
@@ -366,10 +366,9 @@ static auto DiagnoseQualifiedDeclInNonScope(Context& context, SemIRLoc use_loc,
auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
const NameComponent& name) const
-> std::pair<SemIR::NameScopeId, SemIR::GenericInstanceId> {
constexpr std::pair<SemIR::NameScopeId, SemIR::GenericInstanceId>
InvalidResult = {SemIR::NameScopeId::Invalid,
SemIR::GenericInstanceId::Invalid};
-> std::pair<SemIR::NameScopeId, SemIR::SpecificId> {
constexpr std::pair<SemIR::NameScopeId, SemIR::SpecificId> InvalidResult = {
SemIR::NameScopeId::Invalid, SemIR::SpecificId::Invalid};
if (!CheckQualifierIsResolved(*context_, name_context)) {
return InvalidResult;
@@ -396,7 +395,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
return InvalidResult;
}
return {class_info.scope_id,
context_->generics().GetSelfInstance(class_info.generic_id)};
context_->generics().GetSelfSpecific(class_info.generic_id)};
}
case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
const auto& interface_info =
@@ -412,7 +411,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
return InvalidResult;
}
return {interface_info.scope_id,
context_->generics().GetSelfInstance(interface_info.generic_id)};
context_->generics().GetSelfSpecific(interface_info.generic_id)};
}
case CARBON_KIND(SemIR::Namespace resolved_inst): {
auto scope_id = resolved_inst.name_scope_id;
@@ -432,7 +431,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
// be used as a name qualifier.
scope.is_closed_import = false;
}
return {scope_id, SemIR::GenericInstanceId::Invalid};
return {scope_id, SemIR::SpecificId::Invalid};
}
default: {
DiagnoseQualifiedDeclInNonScope(*context_, name_context.loc_id,
+1 -1
View File
@@ -253,7 +253,7 @@ class DeclNameStack {
// the name doesn't resolve to a scope.
auto ResolveAsScope(const NameContext& name_context,
const NameComponent& name) const
-> std::pair<SemIR::NameScopeId, SemIR::GenericInstanceId>;
-> std::pair<SemIR::NameScopeId, SemIR::SpecificId>;
// The linked context.
Context* context_;
+42 -46
View File
@@ -31,7 +31,7 @@ class EvalContext {
public:
explicit EvalContext(
Context& context,
SemIR::GenericInstanceId specific_id = SemIR::GenericInstanceId::Invalid,
SemIR::SpecificId specific_id = SemIR::SpecificId::Invalid,
std::optional<SpecificEvalInfo> specific_eval_info = std::nullopt)
: context_(context),
specific_id_(specific_id),
@@ -45,7 +45,7 @@ class EvalContext {
return SemIR::ConstantId::Invalid;
}
const auto& specific = generic_instances().Get(specific_id_);
const auto& specific = specifics().Get(specific_id_);
auto args = inst_blocks().Get(specific.args_id);
// Bindings past the ones with known arguments can appear as local
@@ -67,14 +67,14 @@ class EvalContext {
// While resolving a specific, map from previous instructions in the eval
// block into their evaluated values. These values won't be present on the
// instance itself yet, so `GetConstantInInstance` won't be able to find
// specific itself yet, so `GetConstantInSpecific` won't be able to find
// them.
if (specific_eval_info_) {
const auto& symbolic_info =
constant_values().GetSymbolicConstant(const_id);
if (symbolic_info.index.is_valid() &&
symbolic_info.generic_id ==
generic_instances().Get(specific_id_).generic_id &&
specifics().Get(specific_id_).generic_id &&
symbolic_info.index.region() == specific_eval_info_->region) {
auto inst_id = specific_eval_info_->values[symbolic_info.index.index()];
CARBON_CHECK(inst_id.is_valid())
@@ -85,7 +85,7 @@ class EvalContext {
}
// Map from a specific constant value to the canonical value.
return GetConstantInInstance(sem_ir(), specific_id_, const_id);
return GetConstantInSpecific(sem_ir(), specific_id_, const_id);
}
// Gets the constant value of the specified instruction in this context.
@@ -124,8 +124,8 @@ class EvalContext {
auto interfaces() -> const ValueStore<SemIR::InterfaceId>& {
return sem_ir().interfaces();
}
auto generic_instances() -> const SemIR::GenericInstanceStore& {
return sem_ir().generic_instances();
auto specifics() -> const SemIR::SpecificStore& {
return sem_ir().specifics();
}
auto type_blocks() -> SemIR::BlockValueStore<SemIR::TypeBlockId>& {
return sem_ir().type_blocks();
@@ -157,7 +157,7 @@ class EvalContext {
// The type-checking context in which we're performing evaluation.
Context& context_;
// The specific that we are evaluating within.
SemIR::GenericInstanceId specific_id_;
SemIR::SpecificId specific_id_;
// If we are currently evaluating an eval block for `specific_id_`,
// information about that evaluation.
std::optional<SpecificEvalInfo> specific_eval_info_;
@@ -320,26 +320,25 @@ static auto GetConstantValue(EvalContext& eval_context,
return type_block_id;
}
// The constant value of a generic instance is the generic instance with the
// corresponding constant values for its arguments.
// The constant value of a specific is the specific with the corresponding
// constant values for its arguments.
static auto GetConstantValue(EvalContext& eval_context,
SemIR::GenericInstanceId instance_id, Phase* phase)
-> SemIR::GenericInstanceId {
if (!instance_id.is_valid()) {
return SemIR::GenericInstanceId::Invalid;
SemIR::SpecificId specific_id, Phase* phase)
-> SemIR::SpecificId {
if (!specific_id.is_valid()) {
return SemIR::SpecificId::Invalid;
}
const auto& instance = eval_context.generic_instances().Get(instance_id);
auto args_id = GetConstantValue(eval_context, instance.args_id, phase);
const auto& specific = eval_context.specifics().Get(specific_id);
auto args_id = GetConstantValue(eval_context, specific.args_id, phase);
if (!args_id.is_valid()) {
return SemIR::GenericInstanceId::Invalid;
return SemIR::SpecificId::Invalid;
}
if (args_id == instance.args_id) {
return instance_id;
if (args_id == specific.args_id) {
return specific_id;
}
return MakeGenericInstance(eval_context.context(), instance.generic_id,
args_id);
return MakeSpecific(eval_context.context(), specific.generic_id, args_id);
}
// Replaces the specified field of the given typed instruction with its constant
@@ -1095,7 +1094,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
eval_context.insts().Get(call.callee_id).type_id());
CARBON_KIND_SWITCH(type_inst) {
case CARBON_KIND(SemIR::GenericClassType generic_class): {
auto instance_id = MakeGenericInstance(
auto specific_id = MakeSpecific(
eval_context.context(),
eval_context.classes().Get(generic_class.class_id).generic_id,
call.args_id);
@@ -1103,21 +1102,20 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
eval_context.context(),
SemIR::ClassType{.type_id = call.type_id,
.class_id = generic_class.class_id,
.instance_id = instance_id},
.specific_id = specific_id},
phase);
}
case CARBON_KIND(SemIR::GenericInterfaceType generic_interface): {
auto instance_id =
MakeGenericInstance(eval_context.context(),
eval_context.interfaces()
.Get(generic_interface.interface_id)
.generic_id,
call.args_id);
auto specific_id = MakeSpecific(eval_context.context(),
eval_context.interfaces()
.Get(generic_interface.interface_id)
.generic_id,
call.args_id);
return MakeConstantResult(
eval_context.context(),
SemIR::InterfaceType{.type_id = call.type_id,
.interface_id = generic_interface.interface_id,
.instance_id = instance_id},
.specific_id = specific_id},
phase);
}
default: {
@@ -1187,13 +1185,13 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
&SemIR::BoundMethod::object_id, &SemIR::BoundMethod::function_id);
case SemIR::ClassType::Kind:
return RebuildIfFieldsAreConstant(eval_context, inst,
&SemIR::ClassType::instance_id);
&SemIR::ClassType::specific_id);
case SemIR::FunctionType::Kind:
return RebuildIfFieldsAreConstant(eval_context, inst,
&SemIR::FunctionType::instance_id);
&SemIR::FunctionType::specific_id);
case SemIR::InterfaceType::Kind:
return RebuildIfFieldsAreConstant(eval_context, inst,
&SemIR::InterfaceType::instance_id);
&SemIR::InterfaceType::specific_id);
case SemIR::InterfaceWitness::Kind:
return RebuildIfFieldsAreConstant(eval_context, inst,
&SemIR::InterfaceWitness::elements_id);
@@ -1288,7 +1286,7 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
eval_context.context(),
SemIR::ClassType{.type_id = SemIR::TypeId::TypeType,
.class_id = class_decl.class_id,
.instance_id = SemIR::GenericInstanceId::Invalid},
.specific_id = SemIR::SpecificId::Invalid},
Phase::Template);
}
case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
@@ -1309,17 +1307,16 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
// A non-generic interface declaration evaluates to the interface type.
return MakeConstantResult(
eval_context.context(),
SemIR::InterfaceType{
.type_id = SemIR::TypeId::TypeType,
.interface_id = interface_decl.interface_id,
.instance_id = SemIR::GenericInstanceId::Invalid},
SemIR::InterfaceType{.type_id = SemIR::TypeId::TypeType,
.interface_id = interface_decl.interface_id,
.specific_id = SemIR::SpecificId::Invalid},
Phase::Template);
}
case CARBON_KIND(SemIR::SpecificConstant instance): {
case CARBON_KIND(SemIR::SpecificConstant specific): {
// Pull the constant value out of the specific.
return SemIR::GetConstantValueInInstance(
eval_context.sem_ir(), instance.instance_id, instance.inst_id);
return SemIR::GetConstantValueInSpecific(
eval_context.sem_ir(), specific.specific_id, specific.inst_id);
}
// These cases are treated as being the unique canonical definition of the
@@ -1371,8 +1368,8 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
const auto& bind_name =
eval_context.entity_names().Get(bind.entity_name_id);
// If we know which instance we're evaluating within and this is an
// argument of that instance, its constant value is the corresponding
// If we know which specific we're evaluating within and this is an
// argument of that specific, its constant value is the corresponding
// argument value.
if (auto value =
eval_context.GetCompileTimeBindValue(bind_name.bind_index);
@@ -1482,11 +1479,10 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
return TryEvalInstInContext(eval_context, inst_id, inst);
}
auto TryEvalBlockForSpecific(Context& context,
SemIR::GenericInstanceId specific_id,
auto TryEvalBlockForSpecific(Context& context, SemIR::SpecificId specific_id,
SemIR::GenericInstIndex::Region region)
-> SemIR::InstBlockId {
auto generic_id = context.generic_instances().Get(specific_id).generic_id;
auto generic_id = context.specifics().Get(specific_id).generic_id;
auto eval_block_id = context.generics().Get(generic_id).GetEvalBlock(region);
auto eval_block = context.inst_blocks().Get(eval_block_id);
+1 -2
View File
@@ -20,8 +20,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
// Evaluates the eval block for a region of a specific. Produces a block
// containing the evaluated constant values of the instructions in the eval
// block.
auto TryEvalBlockForSpecific(Context& context,
SemIR::GenericInstanceId specific_id,
auto TryEvalBlockForSpecific(Context& context, SemIR::SpecificId specific_id,
SemIR::GenericInstIndex::Region region)
-> SemIR::InstBlockId;
+2 -2
View File
@@ -26,7 +26,7 @@ auto CheckFunctionTypeMatches(Context& context,
auto new_return_type_id =
new_function.GetDeclaredReturnType(context.sem_ir());
auto prev_return_type_id = prev_function.GetDeclaredReturnType(
context.sem_ir(), SemIR::GenericInstanceId::Invalid);
context.sem_ir(), SemIR::SpecificId::Invalid);
if (new_return_type_id == SemIR::TypeId::Error ||
prev_return_type_id == SemIR::TypeId::Error) {
return false;
@@ -72,7 +72,7 @@ auto CheckFunctionTypeMatches(Context& context,
auto CheckFunctionReturnType(Context& context, SemIRLoc loc,
SemIR::Function& function,
SemIR::GenericInstanceId specific_id)
SemIR::SpecificId specific_id)
-> SemIR::Function::ReturnSlot {
// If we have already checked the return type, we have nothing to do.
if (function.return_slot != SemIR::Function::ReturnSlot::NotComputed &&
+1 -1
View File
@@ -40,7 +40,7 @@ auto CheckFunctionTypeMatches(Context& context,
// necessary.
auto CheckFunctionReturnType(Context& context, SemIRLoc loc,
SemIR::Function& function,
SemIR::GenericInstanceId specific_id)
SemIR::SpecificId specific_id)
-> SemIR::Function::ReturnSlot;
} // namespace Carbon::Check
+36 -38
View File
@@ -30,9 +30,8 @@ auto StartGenericDefinition(Context& context) -> void {
// Adds an instruction `generic_inst_id` to the eval block for a generic region,
// which is the current instruction block. The instruction `generic_inst_id` is
// expected to compute the value of the constant described by `const_inst_id` in
// each instance of the generic. Forms and returns a corresponding symbolic
// constant ID that refers to the substituted value of that instruction in each
// instance of the generic.
// each specific. Forms and returns a corresponding symbolic constant ID that
// refers to the substituted value of that instruction in each specific.
static auto AddGenericConstantInstToEvalBlock(
Context& context, SemIR::GenericId generic_id,
SemIR::GenericInstIndex::Region region, SemIR::InstId const_inst_id,
@@ -124,9 +123,9 @@ class RebuildGenericConstantInEvalBlockCallbacks final
} // namespace
// Adds instructions to compute the substituted version of `type_id` in each
// instance of a generic into the eval block for the generic, which is the
// current instruction block. Returns a symbolic type ID that refers to the
// substituted type in each instance of the generic.
// specific into the eval block for the generic, which is the current
// instruction block. Returns a symbolic type ID that refers to the substituted
// type in each specific.
static auto AddGenericTypeToEvalBlock(
Context& context, SemIR::GenericId generic_id,
SemIR::GenericInstIndex::Region region,
@@ -142,9 +141,9 @@ static auto AddGenericTypeToEvalBlock(
}
// Adds instructions to compute the substituted value of `inst_id` in each
// instance of a generic into the eval block for the generic, which is the
// current instruction block. Returns a symbolic constant instruction ID that
// refers to the substituted constant value in each instance of the generic.
// specific into the eval block for the generic, which is the current
// instruction block. Returns a symbolic constant instruction ID that refers to
// the substituted constant value in each specific.
static auto AddGenericConstantToEvalBlock(
Context& context, SemIR::GenericId generic_id,
SemIR::GenericInstIndex::Region region,
@@ -164,7 +163,7 @@ static auto AddGenericConstantToEvalBlock(
}
// Builds and returns a block of instructions whose constant values need to be
// evaluated in order to resolve a generic instance.
// evaluated in order to resolve a generic to a specific.
static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
SemIR::GenericInstIndex::Region region)
-> SemIR::InstBlockId {
@@ -209,7 +208,7 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
}
// If the instruction has a symbolic constant value, then make a note that
// we'll need to evaluate this instruction in the generic instance. Update
// we'll need to evaluate this instruction when forming the specific. Update
// the constant value of the instruction to refer to the result of that
// eventual evaluation.
if ((dep_kind & GenericRegionStack::DependencyKind::SymbolicConstant) !=
@@ -253,15 +252,15 @@ auto FinishGenericDecl(Context& context, SemIR::InstId decl_id)
auto generic_id = context.generics().Add(
SemIR::Generic{.decl_id = decl_id,
.bindings_id = bindings_id,
.self_instance_id = SemIR::GenericInstanceId::Invalid});
.self_specific_id = SemIR::SpecificId::Invalid});
auto decl_block_id = MakeGenericEvalBlock(
context, generic_id, SemIR::GenericInstIndex::Region::Declaration);
context.generic_region_stack().Pop();
context.generics().Get(generic_id).decl_block_id = decl_block_id;
auto self_instance_id = MakeGenericSelfInstance(context, generic_id);
context.generics().Get(generic_id).self_instance_id = self_instance_id;
auto self_specific_id = MakeSelfSpecific(context, generic_id);
context.generics().Get(generic_id).self_specific_id = self_specific_id;
return generic_id;
}
@@ -290,33 +289,32 @@ auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)
context.generic_region_stack().Pop();
}
auto MakeGenericInstance(Context& context, SemIR::GenericId generic_id,
SemIR::InstBlockId args_id)
-> SemIR::GenericInstanceId {
auto instance_id = context.generic_instances().GetOrAdd(generic_id, args_id);
auto MakeSpecific(Context& context, SemIR::GenericId generic_id,
SemIR::InstBlockId args_id) -> SemIR::SpecificId {
auto specific_id = context.specifics().GetOrAdd(generic_id, args_id);
// TODO: Remove this once we import generics properly.
if (!generic_id.is_valid()) {
return instance_id;
return specific_id;
}
// If this is the first time we've formed this instance, evaluate its decl
// block to form information about the instance.
if (!context.generic_instances().Get(instance_id).decl_block_id.is_valid()) {
// If this is the first time we've formed this specific, evaluate its decl
// block to form information about the specific.
if (!context.specifics().Get(specific_id).decl_block_id.is_valid()) {
auto decl_block_id = TryEvalBlockForSpecific(
context, instance_id, SemIR::GenericInstIndex::Region::Declaration);
// Note that TryEvalBlockForSpecific may reallocate the list of generic
// instances, so re-lookup the instance here.
context.generic_instances().Get(instance_id).decl_block_id = decl_block_id;
context, specific_id, SemIR::GenericInstIndex::Region::Declaration);
// Note that TryEvalBlockForSpecific may reallocate the list of specifics,
// so re-lookup the specific here.
context.specifics().Get(specific_id).decl_block_id = decl_block_id;
}
return instance_id;
return specific_id;
}
auto MakeGenericSelfInstance(Context& context, SemIR::GenericId generic_id)
-> SemIR::GenericInstanceId {
auto MakeSelfSpecific(Context& context, SemIR::GenericId generic_id)
-> SemIR::SpecificId {
if (!generic_id.is_valid()) {
return SemIR::GenericInstanceId::Invalid;
return SemIR::SpecificId::Invalid;
}
auto& generic = context.generics().Get(generic_id);
@@ -330,16 +328,16 @@ auto MakeGenericSelfInstance(Context& context, SemIR::GenericId generic_id)
}
auto args_id = context.inst_blocks().AddCanonical(arg_ids);
// Build a corresponding instance.
// Build a corresponding specific.
// TODO: This could be made more efficient. We don't need to perform
// substitution here; we know we want identity mappings for all constants and
// types. We could also consider not storing the mapping at all in this case.
return MakeGenericInstance(context, generic_id, args_id);
return MakeSpecific(context, generic_id, args_id);
}
auto ResolveSpecificDefinition(Context& context,
SemIR::GenericInstanceId specific_id) -> bool {
auto& specific = context.generic_instances().Get(specific_id);
auto ResolveSpecificDefinition(Context& context, SemIR::SpecificId specific_id)
-> bool {
auto& specific = context.specifics().Get(specific_id);
auto generic_id = specific.generic_id;
// TODO: Remove this once we import generics properly.
@@ -356,9 +354,9 @@ auto ResolveSpecificDefinition(Context& context,
}
auto definition_block_id = TryEvalBlockForSpecific(
context, specific_id, SemIR::GenericInstIndex::Region::Definition);
// Note that TryEvalBlockForSpecific may reallocate the list of generic
// instances, so re-lookup the instance here.
context.generic_instances().Get(specific_id).definition_block_id =
// Note that TryEvalBlockForSpecific may reallocate the list of specifics,
// so re-lookup the specific here.
context.specifics().Get(specific_id).definition_block_id =
definition_block_id;
}
return true;
+11 -12
View File
@@ -31,26 +31,25 @@ auto FinishGenericRedecl(Context& context, SemIR::InstId decl_id,
auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)
-> void;
// Builds a new generic instance, or finds an existing one if this instance of
// this generic has already been referenced. Performs substitution into the
// Builds a new specific, or finds an existing one if this generic has already
// been referenced with these arguments. Performs substitution into the
// declaration, but not the definition, of the generic.
//
// `args_id` should be a canonical instruction block referring to constants.
auto MakeGenericInstance(Context& context, SemIR::GenericId generic_id,
SemIR::InstBlockId args_id)
-> SemIR::GenericInstanceId;
auto MakeSpecific(Context& context, SemIR::GenericId generic_id,
SemIR::InstBlockId args_id) -> SemIR::SpecificId;
// Builds the generic instance corresponding to the generic itself. For example,
// for a generic `G(T:! type)`, this is `G(T)`. For an invalid `generic_id`,
// returns an invalid instance ID.
auto MakeGenericSelfInstance(Context& context, SemIR::GenericId generic_id)
-> SemIR::GenericInstanceId;
// Builds the specific that describes how the generic should refer to itself.
// For example, for a generic `G(T:! type)`, this is the specific `G(T)`. For an
// invalid `generic_id`, returns an invalid specific ID.
auto MakeSelfSpecific(Context& context, SemIR::GenericId generic_id)
-> SemIR::SpecificId;
// Attempts to resolve the definition of the given specific, by evaluating the
// eval block of the corresponding generic and storing a corresponding value
// block in the specific. Returns false if a definition is not available.
auto ResolveSpecificDefinition(Context& context,
SemIR::GenericInstanceId specific_id) -> bool;
auto ResolveSpecificDefinition(Context& context, SemIR::SpecificId specific_id)
-> bool;
} // namespace Carbon::Check
+4 -4
View File
@@ -252,13 +252,13 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
// declaration.
auto& class_info = context.classes().Get(class_decl.class_id);
if (class_info.is_generic()) {
auto instance_id =
context.generics().GetSelfInstance(class_info.generic_id);
auto specific_id =
context.generics().GetSelfSpecific(class_info.generic_id);
class_info.self_type_id = context.GetTypeIdForTypeConstant(
TryEvalInst(context, SemIR::InstId::Invalid,
SemIR::ClassType{.type_id = SemIR::TypeId::TypeType,
.class_id = class_decl.class_id,
.instance_id = instance_id}));
.specific_id = specific_id}));
} else {
class_info.self_type_id = context.GetTypeIdForTypeInst(class_decl_id);
}
@@ -293,7 +293,7 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id)
// Enter the class scope.
context.scope_stack().Push(
class_decl_id, class_info.scope_id,
context.generics().GetSelfInstance(class_info.generic_id));
context.generics().GetSelfSpecific(class_info.generic_id));
StartGenericDefinition(context);
// Introduce `Self`.
+1 -1
View File
@@ -335,7 +335,7 @@ static auto HandleFunctionDefinitionAfterSignature(
// Check the return type is complete.
CheckFunctionReturnType(context, function.return_storage_id, function,
SemIR::GenericInstanceId::Invalid);
SemIR::SpecificId::Invalid);
// Check the parameter types are complete.
for (auto param_id : llvm::concat<const SemIR::InstId>(
+4 -4
View File
@@ -144,7 +144,7 @@ auto HandleParseNode(Context& context,
// Enter the interface scope.
context.scope_stack().Push(
interface_decl_id, interface_info.scope_id,
context.generics().GetSelfInstance(interface_info.generic_id));
context.generics().GetSelfSpecific(interface_info.generic_id));
StartGenericDefinition(context);
context.inst_block_stack().Push();
@@ -157,13 +157,13 @@ auto HandleParseNode(Context& context,
if (!interface_info.is_defined()) {
SemIR::TypeId self_type_id = SemIR::TypeId::Invalid;
if (interface_info.is_generic()) {
auto instance_id =
context.generics().GetSelfInstance(interface_info.generic_id);
auto specific_id =
context.generics().GetSelfSpecific(interface_info.generic_id);
self_type_id = context.GetTypeIdForTypeConstant(
TryEvalInst(context, SemIR::InstId::Invalid,
SemIR::InterfaceType{.type_id = SemIR::TypeId::TypeType,
.interface_id = interface_id,
.instance_id = instance_id}));
.specific_id = specific_id}));
} else {
self_type_id = context.GetTypeIdForTypeInst(interface_decl_id);
}
+5 -5
View File
@@ -81,18 +81,18 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id,
SemIR::NameId name_id) -> bool {
auto result = context.LookupUnqualifiedName(node_id, name_id);
auto value = context.insts().Get(result.inst_id);
auto type_id = SemIR::GetTypeInInstance(context.sem_ir(), result.instance_id,
auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id,
value.type_id());
CARBON_CHECK(type_id.is_valid()) << "Missing type for " << value;
// If the named entity has a constant value that depends on its generic
// instance, store the instance too.
if (result.instance_id.is_valid() &&
// If the named entity has a constant value that depends on its specific,
// store the specific too.
if (result.specific_id.is_valid() &&
context.constant_values().Get(result.inst_id).is_symbolic()) {
result.inst_id = context.AddInst<SemIR::SpecificConstant>(
node_id, {.type_id = type_id,
.inst_id = result.inst_id,
.instance_id = result.instance_id});
.specific_id = result.specific_id});
}
context.AddInstAndPush<SemIR::NameRef>(
+24 -24
View File
@@ -422,30 +422,30 @@ class ImportRefResolver {
}
// Gets a local argument list corresponding to the arguments of an imported
// generic instance.
auto GetLocalGenericInstanceArgs(SemIR::GenericInstanceId instance_id)
// specific.
auto GetLocalSpecificArgs(SemIR::SpecificId specific_id)
-> llvm::SmallVector<SemIR::InstId> {
if (!instance_id.is_valid()) {
if (!specific_id.is_valid()) {
return {};
}
return GetLocalInstBlockContents(
import_ir_.generic_instances().Get(instance_id).args_id);
import_ir_.specifics().Get(specific_id).args_id);
}
// Gets a local generic instance whose arguments were already imported by
// GetLocalGenericInstanceArgs. Does not add any new work.
auto GetLocalGenericInstance(SemIR::GenericInstanceId instance_id,
llvm::ArrayRef<SemIR::InstId> args)
-> SemIR::GenericInstanceId {
if (!instance_id.is_valid()) {
return SemIR::GenericInstanceId::Invalid;
// Gets a local specific whose arguments were already imported by
// GetLocalSpecificArgs. Does not add any new work.
auto GetLocalSpecific(SemIR::SpecificId specific_id,
llvm::ArrayRef<SemIR::InstId> args)
-> SemIR::SpecificId {
if (!specific_id.is_valid()) {
return SemIR::SpecificId::Invalid;
}
const auto& instance = import_ir_.generic_instances().Get(instance_id);
const auto& specific = import_ir_.specifics().Get(specific_id);
// TODO: Import the generic.
auto generic_id = SemIR::GenericId::Invalid;
auto args_id = GetLocalCanonicalInstBlockId(instance.args_id, args);
// TODO: Also import the generic instance.
return context_.generic_instances().GetOrAdd(generic_id, args_id);
auto args_id = GetLocalCanonicalInstBlockId(specific.args_id, args);
// TODO: Also import the specific.
return context_.specifics().GetOrAdd(generic_id, args_id);
}
// Returns the ConstantId for each parameter's type. Adds unresolved constants
@@ -1046,7 +1046,7 @@ class ImportRefResolver {
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
auto class_const_id =
GetLocalConstantId(import_ir_.classes().Get(inst.class_id).decl_id);
auto args = GetLocalGenericInstanceArgs(inst.instance_id);
auto args = GetLocalSpecificArgs(inst.specific_id);
if (HasNewWork(initial_work)) {
return ResolveResult::Retry();
}
@@ -1061,11 +1061,11 @@ class ImportRefResolver {
} else {
auto generic_class_type = context_.types().GetAs<SemIR::GenericClassType>(
class_const_inst.type_id());
auto instance_id = GetLocalGenericInstance(inst.instance_id, args);
auto specific_id = GetLocalSpecific(inst.specific_id, args);
return ResolveAs<SemIR::ClassType>(
{.type_id = SemIR::TypeId::TypeType,
.class_id = generic_class_type.class_id,
.instance_id = instance_id});
.specific_id = specific_id});
}
}
@@ -1164,7 +1164,7 @@ class ImportRefResolver {
.return_slot = function.return_slot,
.builtin_function_kind = function.builtin_function_kind}});
// TODO: Import this or recompute it.
auto specific_id = SemIR::GenericInstanceId::Invalid;
auto specific_id = SemIR::SpecificId::Invalid;
function_decl.type_id =
context_.GetFunctionType(function_decl.function_id, specific_id);
// Write the function ID into the FunctionDecl.
@@ -1182,8 +1182,8 @@ class ImportRefResolver {
}
auto fn_val = context_.insts().Get(fn_val_id);
CARBON_CHECK(context_.types().Is<SemIR::FunctionType>(fn_val.type_id()));
// TODO: Import the correct generic instance and build a function type
// constant using it.
// TODO: Import the correct specific and build a function type constant
// using it.
return {.const_id = context_.types().GetConstantId(fn_val.type_id())};
}
@@ -1355,7 +1355,7 @@ class ImportRefResolver {
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
auto interface_const_id = GetLocalConstantId(
import_ir_.interfaces().Get(inst.interface_id).decl_id);
auto args = GetLocalGenericInstanceArgs(inst.instance_id);
auto args = GetLocalSpecificArgs(inst.specific_id);
if (HasNewWork(initial_work)) {
return ResolveResult::Retry();
}
@@ -1372,11 +1372,11 @@ class ImportRefResolver {
auto generic_interface_type =
context_.types().GetAs<SemIR::GenericInterfaceType>(
interface_const_inst.type_id());
auto instance_id = GetLocalGenericInstance(inst.instance_id, args);
auto specific_id = GetLocalSpecific(inst.specific_id, args);
return ResolveAs<SemIR::InterfaceType>(
{.type_id = SemIR::TypeId::TypeType,
.interface_id = generic_interface_type.interface_id,
.instance_id = instance_id});
.specific_id = specific_id});
}
}
+9 -9
View File
@@ -27,7 +27,7 @@ static auto GetAsLookupScope(Context& context, Parse::NodeId node_id,
auto base = context.insts().Get(base_id);
if (auto base_as_namespace = base.TryAs<SemIR::Namespace>()) {
return LookupScope{.name_scope_id = base_as_namespace->name_scope_id,
.instance_id = SemIR::GenericInstanceId::Invalid};
.specific_id = SemIR::SpecificId::Invalid};
}
// TODO: Consider refactoring the near-identical class and interface support
// below.
@@ -43,7 +43,7 @@ static auto GetAsLookupScope(Context& context, Parse::NodeId node_id,
});
auto& class_info = context.classes().Get(base_as_class->class_id);
return LookupScope{.name_scope_id = class_info.scope_id,
.instance_id = base_as_class->instance_id};
.specific_id = base_as_class->specific_id};
}
if (auto base_as_interface = base.TryAs<SemIR::InterfaceType>()) {
context.TryToDefineType(
@@ -58,7 +58,7 @@ static auto GetAsLookupScope(Context& context, Parse::NodeId node_id,
auto& interface_info =
context.interfaces().Get(base_as_interface->interface_id);
return LookupScope{.name_scope_id = interface_info.scope_id,
.instance_id = base_as_interface->instance_id};
.specific_id = base_as_interface->specific_id};
}
// TODO: Per the design, if `base_id` is any kind of type, then lookup should
// treat it as a name scope, even if it doesn't have members. For example,
@@ -218,7 +218,7 @@ static auto LookupMemberNameInScope(Context& context, Parse::NodeId node_id,
SemIR::NameId name_id,
SemIR::ConstantId name_scope_const_id,
LookupScope lookup_scope) -> SemIR::InstId {
LookupResult result = {.instance_id = SemIR::GenericInstanceId::Invalid,
LookupResult result = {.specific_id = SemIR::SpecificId::Invalid,
.inst_id = SemIR::InstId::BuiltinError};
if (lookup_scope.name_scope_id.is_valid()) {
result = context.LookupQualifiedName(node_id, name_id, lookup_scope);
@@ -226,18 +226,18 @@ static auto LookupMemberNameInScope(Context& context, Parse::NodeId node_id,
// TODO: This duplicates the work that HandleNameAsExpr does. Factor this out.
auto inst = context.insts().Get(result.inst_id);
auto type_id = SemIR::GetTypeInInstance(context.sem_ir(), result.instance_id,
auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id,
inst.type_id());
CARBON_CHECK(type_id.is_valid()) << "Missing type for member " << inst;
// If the named entity has a constant value that depends on its generic
// instance, store the instance too.
if (result.instance_id.is_valid() &&
// If the named entity has a constant value that depends on its specific,
// store the specific too.
if (result.specific_id.is_valid() &&
context.constant_values().Get(result.inst_id).is_symbolic()) {
result.inst_id = context.AddInst<SemIR::SpecificConstant>(
node_id, {.type_id = type_id,
.inst_id = result.inst_id,
.instance_id = result.instance_id});
.specific_id = result.specific_id});
}
// TODO: Use a different kind of instruction that also references the
+4 -5
View File
@@ -38,10 +38,9 @@ static auto GetOperatorOpFunction(Context& context, Parse::AnyExprId node_id,
return SemIR::InstId::Invalid;
}
// TODO: For a parameterized interface, find the corresponding generic
// instance.
// TODO: For a parameterized interface, find the corresponding specific.
LookupScope scope = {.name_scope_id = interface_scope_id,
.instance_id = SemIR::GenericInstanceId::Invalid};
.specific_id = SemIR::SpecificId::Invalid};
// Lookup `Interface.Op`.
auto op_ident_id = context.identifiers().Add(op.op_name);
@@ -53,8 +52,8 @@ static auto GetOperatorOpFunction(Context& context, Parse::AnyExprId node_id,
}
// Look through import_refs and aliases.
auto op_const_id = GetConstantValueInInstance(
context.sem_ir(), op_result.instance_id, op_result.inst_id);
auto op_const_id = GetConstantValueInSpecific(
context.sem_ir(), op_result.specific_id, op_result.inst_id);
auto op_id = context.constant_values().GetInstId(op_const_id);
// We expect it to be an associated function.
+11 -11
View File
@@ -14,13 +14,13 @@ auto ScopeStack::VerifyOnFinish() -> void {
}
auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
SemIR::GenericInstanceId instance_id,
SemIR::SpecificId specific_id,
bool lexical_lookup_has_load_error) -> void {
// If this scope doesn't have a specific of its own, it lives in the enclosing
// scope's specific, if any.
auto enclosing_instance_id = instance_id;
if (!instance_id.is_valid() && !scope_stack_.empty()) {
enclosing_instance_id = PeekSpecificId();
auto enclosing_specific_id = specific_id;
if (!specific_id.is_valid() && !scope_stack_.empty()) {
enclosing_specific_id = PeekSpecificId();
}
compile_time_binding_stack_.PushArray();
@@ -28,7 +28,7 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
{.index = next_scope_index_,
.scope_inst_id = scope_inst_id,
.scope_id = scope_id,
.instance_id = enclosing_instance_id,
.specific_id = enclosing_specific_id,
.next_compile_time_bind_index = SemIR::CompileTimeBindIndex(
compile_time_binding_stack_.all_values_size()),
.lexical_lookup_has_load_error =
@@ -36,13 +36,13 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
if (scope_id.is_valid()) {
non_lexical_scope_stack_.push_back({.scope_index = next_scope_index_,
.name_scope_id = scope_id,
.instance_id = enclosing_instance_id});
.specific_id = enclosing_specific_id});
} else {
// For lexical lookups, unqualified lookup doesn't know how to find the
// associated generic instance, so if we start adding lexical scopes with
// generic instances, we'll need to somehow track them in lookup.
CARBON_CHECK(!instance_id.is_valid())
<< "Lexical scope should not have an associated generic instance.";
// associated specific, so if we start adding lexical scopes associated with
// specifics, we'll need to somehow track them in lookup.
CARBON_CHECK(!specific_id.is_valid())
<< "Lexical scope should not have an associated specific.";
}
// TODO: Handle this case more gracefully.
@@ -226,7 +226,7 @@ auto ScopeStack::Restore(SuspendedScope scope) -> void {
non_lexical_scope_stack_.push_back(
{.scope_index = scope.entry.index,
.name_scope_id = scope.entry.scope_id,
.instance_id = scope.entry.instance_id});
.specific_id = scope.entry.specific_id});
}
scope_stack_.push_back(std::move(scope.entry));
}
+10 -11
View File
@@ -47,8 +47,8 @@ class ScopeStack {
// The corresponding name scope.
SemIR::NameScopeId name_scope_id;
// The corresponding generic instance.
SemIR::GenericInstanceId instance_id;
// The corresponding specific.
SemIR::SpecificId specific_id;
};
// Information about a scope that has been temporarily removed from the stack.
@@ -58,11 +58,10 @@ class ScopeStack {
// scopes. lexical_lookup_has_load_error is used to limit diagnostics when a
// given namespace may contain a mix of both successful and failed name
// imports.
auto Push(
SemIR::InstId scope_inst_id = SemIR::InstId::Invalid,
SemIR::NameScopeId scope_id = SemIR::NameScopeId::Invalid,
SemIR::GenericInstanceId instance_id = SemIR::GenericInstanceId::Invalid,
bool lexical_lookup_has_load_error = false) -> void;
auto Push(SemIR::InstId scope_inst_id = SemIR::InstId::Invalid,
SemIR::NameScopeId scope_id = SemIR::NameScopeId::Invalid,
SemIR::SpecificId specific_id = SemIR::SpecificId::Invalid,
bool lexical_lookup_has_load_error = false) -> void;
// Pops the top scope from scope_stack_, cleaning up names from
// lexical_lookup_.
@@ -92,8 +91,8 @@ class ScopeStack {
// associated with a specific. This will generally be the self specific of the
// innermost enclosing generic, as there is no way to enter any other specific
// scope.
auto PeekSpecificId() const -> SemIR::GenericInstanceId {
return Peek().instance_id;
auto PeekSpecificId() const -> SemIR::SpecificId {
return Peek().specific_id;
}
// Returns the current scope, if it is of the specified kind. Otherwise,
@@ -181,8 +180,8 @@ class ScopeStack {
// The name scope associated with this entry, if any.
SemIR::NameScopeId scope_id;
// The generic instance associated with this entry, if any.
SemIR::GenericInstanceId instance_id;
// The specific associated with this entry, if any.
SemIR::SpecificId specific_id;
// The next compile-time binding index to allocate in this scope.
SemIR::CompileTimeBindIndex next_compile_time_bind_index;
+11 -11
View File
@@ -82,11 +82,11 @@ static auto PushOperand(Context& context, Worklist& worklist,
worklist.Push(context.types().GetInstId(type_id));
}
break;
case SemIR::IdKind::For<SemIR::GenericInstanceId>:
if (auto instance_id = static_cast<SemIR::GenericInstanceId>(arg);
instance_id.is_valid()) {
case SemIR::IdKind::For<SemIR::SpecificId>:
if (auto specific_id = static_cast<SemIR::SpecificId>(arg);
specific_id.is_valid()) {
PushOperand(context, worklist, SemIR::IdKind::For<SemIR::InstBlockId>,
context.generic_instances().Get(instance_id).args_id.index);
context.specifics().Get(specific_id).args_id.index);
}
break;
default:
@@ -145,17 +145,17 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
}
return new_type_block.GetCanonical().index;
}
case SemIR::IdKind::For<SemIR::GenericInstanceId>: {
auto instance_id = SemIR::GenericInstanceId(arg);
if (!instance_id.is_valid()) {
case SemIR::IdKind::For<SemIR::SpecificId>: {
auto specific_id = SemIR::SpecificId(arg);
if (!specific_id.is_valid()) {
return arg;
}
auto& instance = context.generic_instances().Get(instance_id);
auto& specific = context.specifics().Get(specific_id);
auto args_id =
PopOperand(context, worklist, SemIR::IdKind::For<SemIR::InstBlockId>,
instance.args_id.index);
return MakeGenericInstance(context, instance.generic_id,
SemIR::InstBlockId(args_id))
specific.args_id.index);
return MakeSpecific(context, specific.generic_id,
SemIR::InstBlockId(args_id))
.index;
}
default:
+1 -1
View File
@@ -22,7 +22,7 @@
// CHECK:STDOUT: functions: {}
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics: {}
// CHECK:STDOUT: generic_instances: {}
// CHECK:STDOUT: specifics: {}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -39,7 +39,7 @@ fn B() {
// CHECK:STDOUT: function0: {name: name0, parent_scope: name_scope0, body: [block4]}
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics: {}
// CHECK:STDOUT: generic_instances: {}
// CHECK:STDOUT: specifics: {}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -51,7 +51,7 @@ fn B() {
// CHECK:STDOUT: insts:
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type(instNamespaceType)}
// CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+2)}
// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+3': {kind: TupleType, arg0: type_block0, type: typeTypeType}
// CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type(inst+2)}
// CHECK:STDOUT: 'inst+5': {kind: Return}
@@ -114,7 +114,7 @@ fn B() {
// CHECK:STDOUT: function1: {name: name1, parent_scope: name_scope1}
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics: {}
// CHECK:STDOUT: generic_instances: {}
// CHECK:STDOUT: specifics: {}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -129,13 +129,13 @@ fn B() {
// CHECK:STDOUT: 'inst+1': {kind: ImportDecl, arg0: name1}
// CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type(instNamespaceType)}
// CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+4)}
// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+5': {kind: TupleType, arg0: type_block0, type: typeTypeType}
// CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type(inst+4)}
// CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type(instNamespaceType)}
// CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name0, type: type(inst+10)}
// CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type(inst+10)}
// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type(inst+10)}
// CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type(inst+10)}
// CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type(inst+5)}
@@ -39,7 +39,7 @@ fn B() {
// CHECK:STDOUT: function0: {name: name0, parent_scope: name_scope0, body: [block4]}
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics: {}
// CHECK:STDOUT: generic_instances: {}
// CHECK:STDOUT: specifics: {}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -51,7 +51,7 @@ fn B() {
// CHECK:STDOUT: insts:
// CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type(instNamespaceType)}
// CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+2)}
// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+3': {kind: TupleType, arg0: type_block0, type: typeTypeType}
// CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type(inst+2)}
// CHECK:STDOUT: 'inst+5': {kind: Return}
@@ -93,7 +93,7 @@ fn B() {
// CHECK:STDOUT: function1: {name: name1, parent_scope: name_scope1}
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics: {}
// CHECK:STDOUT: generic_instances: {}
// CHECK:STDOUT: specifics: {}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -108,13 +108,13 @@ fn B() {
// CHECK:STDOUT: 'inst+1': {kind: ImportDecl, arg0: name1}
// CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type(instNamespaceType)}
// CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+4)}
// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+5': {kind: TupleType, arg0: type_block0, type: typeTypeType}
// CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type(inst+4)}
// CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type(instNamespaceType)}
// CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name0, type: type(inst+10)}
// CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type(inst+10)}
// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type(inst+10)}
// CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type(inst+10)}
// CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type(inst+5)}
@@ -30,7 +30,7 @@ fn Foo(n: ()) -> ((), ()) {
// CHECK:STDOUT: function0: {name: name0, parent_scope: name_scope0, return_storage: inst+13, return_slot: present, body: [block7]}
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics: {}
// CHECK:STDOUT: generic_instances: {}
// CHECK:STDOUT: specifics: {}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -60,7 +60,7 @@ fn Foo(n: ()) -> ((), ()) {
// CHECK:STDOUT: 'inst+12': {kind: Converted, arg0: inst+9, arg1: inst+8, type: typeTypeType}
// CHECK:STDOUT: 'inst+13': {kind: VarStorage, arg0: nameReturnSlot, type: type(inst+8)}
// CHECK:STDOUT: 'inst+14': {kind: FunctionDecl, arg0: function0, arg1: block6, type: type(inst+15)}
// CHECK:STDOUT: 'inst+15': {kind: FunctionType, arg0: function0, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+15': {kind: FunctionType, arg0: function0, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+16': {kind: StructValue, arg0: empty, type: type(inst+15)}
// CHECK:STDOUT: 'inst+17': {kind: PointerType, arg0: type(inst+8), type: typeTypeType}
// CHECK:STDOUT: 'inst+18': {kind: NameRef, arg0: name1, arg1: inst+5, type: type(inst+1)}
+3 -3
View File
@@ -32,8 +32,8 @@ fn Foo[T:! type](n: T) -> (T, ()) {
// CHECK:STDOUT: classes: {}
// CHECK:STDOUT: generics:
// CHECK:STDOUT: generic0: {decl: inst+16, bindings: block8}
// CHECK:STDOUT: generic_instances:
// CHECK:STDOUT: genericInstance0: {generic: generic0, args: block10}
// CHECK:STDOUT: specifics:
// CHECK:STDOUT: specific0: {generic: generic0, args: block10}
// CHECK:STDOUT: types:
// CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType}
// CHECK:STDOUT: typeError: {kind: copy, type: typeError}
@@ -77,7 +77,7 @@ fn Foo[T:! type](n: T) -> (T, ()) {
// CHECK:STDOUT: 'inst+17': {kind: BindSymbolicName, arg0: entity_name0, arg1: inst<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+18': {kind: TupleType, arg0: type_block3, type: typeTypeType}
// CHECK:STDOUT: 'inst+19': {kind: TupleType, arg0: type_block3, type: typeTypeType}
// CHECK:STDOUT: 'inst+20': {kind: FunctionType, arg0: function0, arg1: genericInstance<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+20': {kind: FunctionType, arg0: function0, arg1: specific<invalid>, type: typeTypeType}
// CHECK:STDOUT: 'inst+21': {kind: StructValue, arg0: empty, type: type(inst+20)}
// CHECK:STDOUT: 'inst+22': {kind: PointerType, arg0: type(symbolicConstant1), type: typeTypeType}
// CHECK:STDOUT: 'inst+23': {kind: NameRef, arg0: name2, arg1: inst+6, type: type(symbolicConstant2)}
+1 -1
View File
@@ -20,7 +20,7 @@ struct InvalidNodeId {};
// contain any of the information about the node, and serve as a handle that
// can be used with the underlying tree to query for detailed information.
struct NodeId : public IdBase {
// An explicitly invalid instance.
// An explicitly invalid node ID.
static constexpr InvalidNodeId Invalid;
using IdBase::IdBase;
+2 -3
View File
@@ -152,7 +152,7 @@ auto File::OutputYaml(bool include_builtins) const -> Yaml::OutputMapping {
map.Add("functions", functions_.OutputYaml());
map.Add("classes", classes_.OutputYaml());
map.Add("generics", generics_.OutputYaml());
map.Add("generic_instances", generic_instances_.OutputYaml());
map.Add("specifics", specifics_.OutputYaml());
map.Add("types", types_.OutputYaml());
map.Add("type_blocks", type_blocks_.OutputYaml());
map.Add(
@@ -201,8 +201,7 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
mem_usage.Collect(MemUsage::ConcatLabel(label, "interfaces_"), interfaces_);
mem_usage.Collect(MemUsage::ConcatLabel(label, "impls_"), impls_);
mem_usage.Collect(MemUsage::ConcatLabel(label, "generics_"), generics_);
mem_usage.Collect(MemUsage::ConcatLabel(label, "generic_instances_"),
generic_instances_);
mem_usage.Collect(MemUsage::ConcatLabel(label, "specifics_"), specifics_);
mem_usage.Collect(MemUsage::ConcatLabel(label, "import_irs_"), import_irs_);
mem_usage.Collect(MemUsage::ConcatLabel(label, "import_ir_insts_"),
import_ir_insts_);
+4 -8
View File
@@ -125,12 +125,8 @@ class File : public Printable<File> {
auto impls() const -> const ImplStore& { return impls_; }
auto generics() -> GenericStore& { return generics_; }
auto generics() const -> const GenericStore& { return generics_; }
auto generic_instances() -> GenericInstanceStore& {
return generic_instances_;
}
auto generic_instances() const -> const GenericInstanceStore& {
return generic_instances_;
}
auto specifics() -> SpecificStore& { return specifics_; }
auto specifics() const -> const SpecificStore& { return specifics_; }
auto import_irs() -> ValueStore<ImportIRId>& { return import_irs_; }
auto import_irs() const -> const ValueStore<ImportIRId>& {
return import_irs_;
@@ -215,8 +211,8 @@ class File : public Printable<File> {
// Storage for generics.
GenericStore generics_;
// Storage for instances of generics.
GenericInstanceStore generic_instances_;
// Storage for specifics.
SpecificStore specifics_;
// Related IRs. There are some fixed entries at the start; see ImportIRId.
ValueStore<ImportIRId> import_irs_;
+14 -15
View File
@@ -69,8 +69,8 @@ class FormatterImpl {
FormatFunction(FunctionId(i));
}
for (int i : llvm::seq(sem_ir_.generic_instances().size())) {
FormatSpecific(GenericInstanceId(i));
for (int i : llvm::seq(sem_ir_.specifics().size())) {
FormatSpecific(SpecificId(i));
}
// End-of-file newline.
@@ -370,8 +370,7 @@ class FormatterImpl {
out_ << '\n';
}
auto FormatSpecificRegion(const Generic& generic,
const GenericInstance& specific,
auto FormatSpecificRegion(const Generic& generic, const Specific& specific,
GenericInstIndex::Region region,
llvm::StringRef region_name) -> void {
if (!specific.GetValueBlock(region).is_valid()) {
@@ -409,8 +408,8 @@ class FormatterImpl {
}
}
auto FormatSpecific(GenericInstanceId id) -> void {
const auto& specific = sem_ir_.generic_instances().Get(id);
auto FormatSpecific(SpecificId id) -> void {
const auto& specific = sem_ir_.specifics().Get(id);
out_ << "\n";
@@ -764,8 +763,8 @@ class FormatterImpl {
}
auto FormatInstRHS(FunctionType inst) -> void {
if (inst.instance_id.is_valid()) {
FormatArgs(inst.function_id, inst.instance_id);
if (inst.specific_id.is_valid()) {
FormatArgs(inst.function_id, inst.specific_id);
} else {
FormatArgs(inst.function_id);
}
@@ -777,8 +776,8 @@ class FormatterImpl {
}
auto FormatInstRHS(ClassType inst) -> void {
if (inst.instance_id.is_valid()) {
FormatArgs(inst.class_id, inst.instance_id);
if (inst.specific_id.is_valid()) {
FormatArgs(inst.class_id, inst.specific_id);
} else {
FormatArgs(inst.class_id);
}
@@ -795,8 +794,8 @@ class FormatterImpl {
}
auto FormatInstRHS(InterfaceType inst) -> void {
if (inst.instance_id.is_valid()) {
FormatArgs(inst.interface_id, inst.instance_id);
if (inst.specific_id.is_valid()) {
FormatArgs(inst.interface_id, inst.specific_id);
} else {
FormatArgs(inst.interface_id);
}
@@ -949,7 +948,7 @@ class FormatterImpl {
out_ << ')';
}
auto FormatArg(GenericInstanceId id) -> void { FormatName(id); }
auto FormatArg(SpecificId id) -> void { FormatName(id); }
auto FormatArg(RealId id) -> void {
// TODO: Format with a `.` when the exponent is near zero.
@@ -997,8 +996,8 @@ class FormatterImpl {
out_ << inst_namer_->GetNameFor(id);
}
auto FormatName(GenericInstanceId id) -> void {
const auto& specific = sem_ir_.generic_instances().Get(id);
auto FormatName(SpecificId id) -> void {
const auto& specific = sem_ir_.specifics().Get(id);
FormatName(specific.generic_id);
FormatArg(specific.args_id);
}
+4 -5
View File
@@ -12,7 +12,7 @@ namespace Carbon::SemIR {
auto GetCalleeFunction(const File& sem_ir, InstId callee_id) -> CalleeFunction {
CalleeFunction result = {.function_id = FunctionId::Invalid,
.instance_id = GenericInstanceId::Invalid,
.specific_id = SpecificId::Invalid,
.self_id = InstId::Invalid,
.is_error = false};
@@ -38,17 +38,16 @@ auto GetCalleeFunction(const File& sem_ir, InstId callee_id) -> CalleeFunction {
}
result.function_id = fn_type->function_id;
result.instance_id = fn_type->instance_id;
result.specific_id = fn_type->specific_id;
return result;
}
auto Function::GetDeclaredReturnType(const File& file,
GenericInstanceId specific_id) const
-> TypeId {
SpecificId specific_id) const -> TypeId {
if (!return_storage_id.is_valid()) {
return TypeId::Invalid;
}
return GetTypeInInstance(file, specific_id,
return GetTypeInSpecific(file, specific_id,
file.insts().Get(return_storage_id).type_id());
}
+5 -5
View File
@@ -98,13 +98,13 @@ struct Function : public EntityWithParamsBase,
static auto GetParamFromParamRefId(const File& sem_ir, InstId param_ref_id)
-> std::pair<InstId, Param>;
// Gets the declared return type for a specific instance of this function, or
// Gets the declared return type for a specific version of this function, or
// the canonical return type for the original declaration no specific is
// specified. Returns `Invalid` if no return type was specified, in which
// case the effective return type is an empty tuple.
auto GetDeclaredReturnType(const File& file,
GenericInstanceId specific_id =
GenericInstanceId::Invalid) const -> TypeId;
SpecificId specific_id = SpecificId::Invalid) const
-> TypeId;
// Returns whether the function has a return slot. Can only be called for a
// function that has either been called or defined, otherwise this is not
@@ -126,8 +126,8 @@ class File;
struct CalleeFunction {
// The function. Invalid if not a function.
SemIR::FunctionId function_id;
// The generic instance that contains the function.
SemIR::GenericInstanceId instance_id;
// The specific that contains the function.
SemIR::SpecificId specific_id;
// The bound `self` parameter. Invalid if not a method.
SemIR::InstId self_id;
// True if an error instruction was found.
+31 -34
View File
@@ -8,10 +8,9 @@
namespace Carbon::SemIR {
class GenericInstanceStore::KeyContext
: public TranslatingKeyContext<KeyContext> {
class SpecificStore::KeyContext : public TranslatingKeyContext<KeyContext> {
public:
// A lookup key for a generic instance.
// A lookup key for a specific.
struct Key {
GenericId generic_id;
InstBlockId args_id;
@@ -19,41 +18,39 @@ class GenericInstanceStore::KeyContext
friend auto operator==(const Key&, const Key&) -> bool = default;
};
explicit KeyContext(llvm::ArrayRef<GenericInstance> instances)
: instances_(instances) {}
explicit KeyContext(llvm::ArrayRef<Specific> specifics)
: specifics_(specifics) {}
auto TranslateKey(GenericInstanceId id) const -> Key {
const auto& instance = instances_[id.index];
return {.generic_id = instance.generic_id, .args_id = instance.args_id};
auto TranslateKey(SpecificId id) const -> Key {
const auto& specific = specifics_[id.index];
return {.generic_id = specific.generic_id, .args_id = specific.args_id};
}
private:
llvm::ArrayRef<GenericInstance> instances_;
llvm::ArrayRef<Specific> specifics_;
};
auto GenericInstanceStore::GetOrAdd(GenericId generic_id, InstBlockId args_id)
-> GenericInstanceId {
auto SpecificStore::GetOrAdd(GenericId generic_id, InstBlockId args_id)
-> SpecificId {
return lookup_table_
.Insert(
KeyContext::Key{.generic_id = generic_id, .args_id = args_id},
[&] {
return generic_instances_.Add(
return specifics_.Add(
{.generic_id = generic_id, .args_id = args_id});
},
KeyContext(generic_instances_.array_ref()))
KeyContext(specifics_.array_ref()))
.key();
}
auto GenericInstanceStore::CollectMemUsage(MemUsage& mem_usage,
llvm::StringRef label) const
-> void {
mem_usage.Collect(MemUsage::ConcatLabel(label, "generic_instances_"),
generic_instances_);
auto SpecificStore::CollectMemUsage(MemUsage& mem_usage,
llvm::StringRef label) const -> void {
mem_usage.Collect(MemUsage::ConcatLabel(label, "specifics_"), specifics_);
mem_usage.Add(MemUsage::ConcatLabel(label, "lookup_table_"), lookup_table_,
KeyContext(generic_instances_.array_ref()));
KeyContext(specifics_.array_ref()));
}
auto GetConstantInInstance(const File& sem_ir, GenericInstanceId instance_id,
auto GetConstantInSpecific(const File& sem_ir, SpecificId specific_id,
ConstantId const_id) -> ConstantId {
if (!const_id.is_symbolic()) {
// Type does not depend on a generic parameter.
@@ -62,43 +59,43 @@ auto GetConstantInInstance(const File& sem_ir, GenericInstanceId instance_id,
const auto& symbolic = sem_ir.constant_values().GetSymbolicConstant(const_id);
if (!symbolic.generic_id.is_valid()) {
// Constant is an abstract symbolic constant, not an instance-specific one.
// Constant is an abstract symbolic constant, not associated with some
// particular generic.
return const_id;
}
if (!instance_id.is_valid()) {
// TODO: We have a generic constant but no instance. Investigate whether we
if (!specific_id.is_valid()) {
// TODO: We have a generic constant but no specific. Investigate whether we
// can CHECK-fail here. For now, produce the canonical value of the
// constant.
return sem_ir.constant_values().Get(symbolic.inst_id);
}
const auto& specific = sem_ir.generic_instances().Get(instance_id);
const auto& specific = sem_ir.specifics().Get(specific_id);
if (specific.generic_id != symbolic.generic_id) {
// TODO: Given an instance for the wrong generic. If the symbolic constant
// TODO: Given an specific for the wrong generic. If the symbolic constant
// is from an enclosing generic, take the value from the corresponding
// instance. Otherwise, CHECK-fail.
// specific. Otherwise, CHECK-fail.
return sem_ir.constant_values().Get(symbolic.inst_id);
}
auto value_block_id = specific.GetValueBlock(symbolic.index.region());
CARBON_CHECK(value_block_id.is_valid())
<< "Queried region of " << instance_id << " before it was resolved.";
<< "Queried region of " << specific_id << " before it was resolved.";
return sem_ir.constant_values().Get(
sem_ir.inst_blocks().Get(value_block_id)[symbolic.index.index()]);
}
auto GetConstantValueInInstance(const File& sem_ir,
GenericInstanceId instance_id, InstId inst_id)
-> ConstantId {
return GetConstantInInstance(sem_ir, instance_id,
auto GetConstantValueInSpecific(const File& sem_ir, SpecificId specific_id,
InstId inst_id) -> ConstantId {
return GetConstantInSpecific(sem_ir, specific_id,
sem_ir.constant_values().Get(inst_id));
}
auto GetTypeInInstance(const File& sem_ir, GenericInstanceId instance_id,
auto GetTypeInSpecific(const File& sem_ir, SpecificId specific_id,
TypeId type_id) -> TypeId {
return TypeId::ForTypeConstant(GetConstantInInstance(
sem_ir, instance_id, sem_ir.types().GetConstantId(type_id)));
return TypeId::ForTypeConstant(GetConstantInSpecific(
sem_ir, specific_id, sem_ir.types().GetConstantId(type_id)));
}
} // namespace Carbon::SemIR
+42 -43
View File
@@ -37,10 +37,10 @@ struct Generic : public Printable<Generic> {
// The index in this block will match the `bind_index` in the name binding
// instruction's `EntityName`.
InstBlockId bindings_id;
// The self instance of this generic, which is an instance where every generic
// parameter's argument is that same parameter. For example, the self instance
// The self specific of this generic, which is a specific where every generic
// parameter's argument is that same parameter. For example, the self specific
// of `Vector(T:! type)` is `Vector(T)`.
GenericInstanceId self_instance_id;
SpecificId self_specific_id;
// The following members are set at the end of the corresponding region of the
// generic.
@@ -54,19 +54,18 @@ struct Generic : public Printable<Generic> {
// Provides storage for generics.
class GenericStore : public ValueStore<GenericId> {
public:
// Get the self-instance for a generic, or an invalid instance for an invalid
// Get the self specific for a generic, or an invalid specific for an invalid
// generic ID.
auto GetSelfInstance(GenericId id) -> GenericInstanceId {
return id.is_valid() ? Get(id).self_instance_id
: GenericInstanceId::Invalid;
auto GetSelfSpecific(GenericId id) -> SpecificId {
return id.is_valid() ? Get(id).self_specific_id : SpecificId::Invalid;
}
};
// An instance of a generic entity, such as an instance of a generic function.
// For each construct that depends on a compile-time parameter in the generic
// entity, this contains the corresponding non-generic value. This includes
// A specific, which is the combination of a generic and specified generic
// arguments. For each construct that depends on a compile-time parameter in the
// generic entity, this contains the corresponding specific value. This includes
// values for the compile-time parameters themselves.
struct GenericInstance : Printable<GenericInstance> {
struct Specific : Printable<Specific> {
auto Print(llvm::raw_ostream& out) const -> void {
out << "{generic: " << generic_id << ", args: " << args_id << "}";
}
@@ -82,7 +81,7 @@ struct GenericInstance : Printable<GenericInstance> {
: definition_block_id;
}
// The generic that this is an instance of.
// The generic that this is a specific version of.
GenericId generic_id;
// Argument values, corresponding to the bindings in `Generic::bindings_id`.
InstBlockId args_id;
@@ -96,64 +95,64 @@ struct GenericInstance : Printable<GenericInstance> {
InstBlockId definition_block_id = InstBlockId::Invalid;
};
// Provides storage for deduplicated instances of generics.
class GenericInstanceStore : public Yaml::Printable<GenericInstanceStore> {
// Provides storage for deduplicated specifics, which represent generics plus
// their associated generic argument list.
class SpecificStore : public Yaml::Printable<SpecificStore> {
public:
// Adds a new generic instance, or gets the existing generic instance for a
// specified generic and argument list. Returns the ID of the generic
// instance. The argument IDs must be for instructions in the constant block,
// and must be a canonical instruction block ID.
auto GetOrAdd(GenericId generic_id, InstBlockId args_id) -> GenericInstanceId;
// Adds a new specific, or gets the existing specific for a specified generic
// and argument list. Returns the ID of the specific. The argument IDs must be
// for instructions in the constant block, and must be a canonical instruction
// block ID.
auto GetOrAdd(GenericId generic_id, InstBlockId args_id) -> SpecificId;
// Gets the specified generic instance.
auto Get(GenericInstanceId instance_id) const -> const GenericInstance& {
return generic_instances_.Get(instance_id);
// Gets the specific with the given ID.
auto Get(SpecificId specific_id) const -> const Specific& {
return specifics_.Get(specific_id);
}
// Gets the specified generic instance.
auto Get(GenericInstanceId instance_id) -> GenericInstance& {
return generic_instances_.Get(instance_id);
// Gets the specific with the given ID.
auto Get(SpecificId specific_id) -> Specific& {
return specifics_.Get(specific_id);
}
// These are to support printable structures, and are not guaranteed.
auto OutputYaml() const -> Yaml::OutputMapping {
return generic_instances_.OutputYaml();
return specifics_.OutputYaml();
}
// Collects memory usage of members.
auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
-> void;
auto array_ref() const -> llvm::ArrayRef<GenericInstance> {
return generic_instances_.array_ref();
auto array_ref() const -> llvm::ArrayRef<Specific> {
return specifics_.array_ref();
}
auto size() const -> size_t { return generic_instances_.size(); }
auto size() const -> size_t { return specifics_.size(); }
private:
// Context for hashing keys.
class KeyContext;
ValueStore<GenericInstanceId> generic_instances_;
Carbon::Set<GenericInstanceId, 0, KeyContext> lookup_table_;
ValueStore<SpecificId> specifics_;
Carbon::Set<SpecificId, 0, KeyContext> lookup_table_;
};
// Gets the substituted value of a constant within a specified instance of a
// generic. Note that this does not perform substitution, and will return
// Gets the substituted value of a potentially generic constant within a
// specific. Note that this does not perform substitution, and will return
// `Invalid` if the substituted constant value is not yet known.
auto GetConstantInInstance(const File& sem_ir, GenericInstanceId instance_id,
auto GetConstantInSpecific(const File& sem_ir, SpecificId specific_id,
ConstantId const_id) -> ConstantId;
// Gets the substituted constant value of an instruction within a specified
// instance of a generic. Note that this does not perform substitution, and will
// Gets the substituted constant value of a potentially generic instruction
// within a specific. Note that this does not perform substitution, and will
// return `Invalid` if the substituted constant value is not yet known.
auto GetConstantValueInInstance(const File& sem_ir,
GenericInstanceId instance_id, InstId inst_id)
-> ConstantId;
auto GetConstantValueInSpecific(const File& sem_ir, SpecificId specific_id,
InstId inst_id) -> ConstantId;
// Gets the substituted value of a type within a specified instance of a
// generic. Note that this does not perform substitution, and will return
// `Invalid` if the substituted type is not yet known.
auto GetTypeInInstance(const File& sem_ir, GenericInstanceId instance_id,
// Gets the substituted value of a potentially generic type within a specific.
// Note that this does not perform substitution, and will return `Invalid` if
// the substituted type is not yet known.
auto GetTypeInSpecific(const File& sem_ir, SpecificId specific_id,
TypeId type_id) -> TypeId;
} // namespace Carbon::SemIR
+3 -3
View File
@@ -121,9 +121,9 @@ using IdKind = TypeEnum<
IntId, RealId, FloatId, StringLiteralValueId,
// From sem_ir/id.h.
InstId, ConstantId, EntityNameId, CompileTimeBindIndex, FunctionId, ClassId,
InterfaceId, ImplId, GenericId, GenericInstanceId, ImportIRId,
ImportIRInstId, LocId, BoolValue, IntKind, NameId, NameScopeId, InstBlockId,
TypeId, TypeBlockId, ElementIndex, FloatKind>;
InterfaceId, ImplId, GenericId, SpecificId, ImportIRId, ImportIRInstId,
LocId, BoolValue, IntKind, NameId, NameScopeId, InstBlockId, TypeId,
TypeBlockId, ElementIndex, FloatKind>;
} // namespace Carbon::SemIR
+12 -11
View File
@@ -22,7 +22,7 @@ struct EntityName;
struct Class;
struct Function;
struct Generic;
struct GenericInstance;
struct Specific;
struct ImportIR;
struct ImportIRInst;
struct Interface;
@@ -319,27 +319,28 @@ struct GenericId : public IdBase, public Printable<GenericId> {
constexpr GenericId GenericId::Invalid = GenericId(InvalidIndex);
// The ID of an instance of a generic.
struct GenericInstanceId : public IdBase, public Printable<GenericInstanceId> {
using ValueType = GenericInstance;
// The ID of a specific, which is the result of specifying the generic arguments
// for a generic.
struct SpecificId : public IdBase, public Printable<SpecificId> {
using ValueType = Specific;
// An explicitly invalid ID. This is typically used to represent a non-generic
// instance.
static const GenericInstanceId Invalid;
// entity.
static const SpecificId Invalid;
using IdBase::IdBase;
auto Print(llvm::raw_ostream& out) const -> void {
out << "genericInstance";
out << "specific";
IdBase::Print(out);
}
};
constexpr GenericInstanceId GenericInstanceId::Invalid =
GenericInstanceId(InvalidIndex);
constexpr SpecificId SpecificId::Invalid = SpecificId(InvalidIndex);
// The index of an instruction that depends on generic parameters within a
// generic, and the value of that instruction within the instances of that
// generic. This is a pair of a region and an index, stored in 32 bits.
// region of a generic. A corresponding specific version of the instruction can
// be found in each specific corresponding to that generic. This is a pair of a
// region and an index, stored in 32 bits.
struct GenericInstIndex : public IndexBase, public Printable<GenericInstIndex> {
// Where the value is first used within the generic.
enum Region : uint8_t {
+7 -8
View File
@@ -450,7 +450,7 @@ struct ClassInit {
InstId dest_id;
};
// The type for a class, either non-generic or parameterized generic instance.
// The type for a class, either non-generic or specific.
struct ClassType {
static constexpr auto Kind = InstKind::ClassType.Define<Parse::NodeId>(
{.ir_name = "class_type",
@@ -459,7 +459,7 @@ struct ClassType {
TypeId type_id;
ClassId class_id;
GenericInstanceId instance_id;
SpecificId specific_id;
};
// Indicates `const` on a type, such as `var x: const i32`.
@@ -575,7 +575,7 @@ struct FunctionType {
TypeId type_id;
FunctionId function_id;
GenericInstanceId instance_id;
SpecificId specific_id;
};
// The type of the name of a generic class. The corresponding value is an empty
@@ -690,8 +690,7 @@ struct InterfaceDecl {
InstBlockId decl_block_id;
};
// The type for an interface, either non-generic or parameterized generic
// instance.
// The type for an interface, either non-generic or specific.
struct InterfaceType {
static constexpr auto Kind = InstKind::InterfaceType.Define<Parse::NodeId>(
{.ir_name = "interface_type",
@@ -700,7 +699,7 @@ struct InterfaceType {
TypeId type_id;
InterfaceId interface_id;
GenericInstanceId instance_id;
SpecificId specific_id;
};
// A witness that a type implements an interface.
@@ -823,7 +822,7 @@ struct ReturnExpr {
};
// Given an instruction with a constant value that depends on a generic
// parameter, selects an instance of that instruction with the constant value
// parameter, selects a version of that instruction with the constant value
// corresponding to a particular specific.
//
// TODO: We only form these as the instruction referenced by a `NameRef`.
@@ -835,7 +834,7 @@ struct SpecificConstant {
TypeId type_id;
InstId inst_id;
GenericInstanceId instance_id;
SpecificId specific_id;
};
// Splices a block into the location where this appears. This may be an
+1 -1
View File
@@ -62,7 +62,7 @@ TEST(SemIRTest, YAML) {
Pair("functions", Yaml::Mapping(SizeIs(1))),
Pair("classes", Yaml::Mapping(SizeIs(0))),
Pair("generics", Yaml::Mapping(SizeIs(0))),
Pair("generic_instances", Yaml::Mapping(SizeIs(0))),
Pair("specifics", Yaml::Mapping(SizeIs(0))),
Pair("types", Yaml::Mapping(Each(type_builtin))),
Pair("type_blocks", Yaml::Mapping(SizeIs(Ge(1)))),
Pair("insts",