mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Introduce TypeInstId (#5288)
TypeInstId is an InstId whose constant value has a type of TypeType. This includes: - Type value instructions, the `ClassType` or `IntLiteralType` instructions. - Constraint value instructions, which are the `FacetType` and `TypeType` instructions, each of which also have type TypeType. TypeInstId encodes in the type system that it is safe to convert the instruction's value to a TypeId, and CHECKs at construction that this invariant is maintained. --------- Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
co-authored by
Richard Smith
parent
03a31bd0de
commit
cf57c85545
@@ -1076,16 +1076,16 @@ static auto PerformBuiltinConversion(
|
||||
// `FacetValue`, which requires an instruction of type `TypeType`. So if
|
||||
// we are converting from a facet value, we get its `type` via an extra
|
||||
// `FacetAccessType` instruction.
|
||||
auto type_inst_id = SemIR::InstId::None;
|
||||
auto type_inst_id = SemIR::TypeInstId::None;
|
||||
if (sem_ir.types().Is<SemIR::FacetType>(value_type_id)) {
|
||||
type_inst_id =
|
||||
type_inst_id = context.types().GetAsTypeInstId(
|
||||
AddInst(context, loc_id,
|
||||
SemIR::FacetAccessType{
|
||||
.type_id = SemIR::TypeType::SingletonTypeId,
|
||||
.facet_value_inst_id = const_value_id,
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
type_inst_id = const_value_id;
|
||||
type_inst_id = context.types().GetAsTypeInstId(const_value_id);
|
||||
}
|
||||
return AddInst<SemIR::FacetValue>(
|
||||
context, loc_id,
|
||||
@@ -1470,7 +1470,7 @@ auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id,
|
||||
auto type_inst_id = ConvertToValueOfType(context, loc_id, value_id,
|
||||
SemIR::TypeType::SingletonTypeId);
|
||||
if (type_inst_id == SemIR::ErrorInst::SingletonInstId) {
|
||||
return {.inst_id = type_inst_id,
|
||||
return {.inst_id = SemIR::ErrorInst::SingletonTypeInstId,
|
||||
.type_id = SemIR::ErrorInst::SingletonTypeId};
|
||||
}
|
||||
|
||||
@@ -1481,11 +1481,11 @@ auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id,
|
||||
"cannot evaluate type expression");
|
||||
context.emitter().Emit(loc_id, TypeExprEvaluationFailure);
|
||||
}
|
||||
return {.inst_id = SemIR::ErrorInst::SingletonInstId,
|
||||
return {.inst_id = SemIR::ErrorInst::SingletonTypeInstId,
|
||||
.type_id = SemIR::ErrorInst::SingletonTypeId};
|
||||
}
|
||||
|
||||
return {.inst_id = type_inst_id,
|
||||
return {.inst_id = context.types().GetAsTypeInstId(type_inst_id),
|
||||
.type_id = context.types().GetTypeIdForTypeConstantId(type_const_id)};
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
|
||||
// A type that has been converted for use as a type expression.
|
||||
struct TypeExpr {
|
||||
// The converted expression of type `type`, or `ErrorInst::SingletonInstId`.
|
||||
SemIR::InstId inst_id;
|
||||
SemIR::TypeInstId inst_id;
|
||||
// The corresponding type, or `ErrorInst::SingletonTypeId`.
|
||||
SemIR::TypeId type_id;
|
||||
};
|
||||
|
||||
@@ -130,6 +130,10 @@ class DeductionWorklist {
|
||||
Add(inst_id, SemIR::InstId(arg), needs_substitution);
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::TypeInstId inst_id): {
|
||||
Add(inst_id, SemIR::InstId(arg), needs_substitution);
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::StructTypeFieldsId fields_id): {
|
||||
AddAll(fields_id, SemIR::StructTypeFieldsId(arg), needs_substitution);
|
||||
break;
|
||||
|
||||
@@ -421,6 +421,16 @@ static auto GetConstantValue(EvalContext& eval_context,
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
static auto GetConstantValue(EvalContext& eval_context,
|
||||
SemIR::TypeInstId inst_id, Phase* phase)
|
||||
-> SemIR::TypeInstId {
|
||||
// The input instruction is a TypeInstId, and eval does not change concrete
|
||||
// types (like TypeType which TypeInstId implies), so the result is also a
|
||||
// valid TypeInstId.
|
||||
return SemIR::TypeInstId::UnsafeMake(GetConstantValue(
|
||||
eval_context, static_cast<SemIR::InstId>(inst_id), phase));
|
||||
}
|
||||
|
||||
// Explicitly discard a `DestInstId`, because we should not be using the
|
||||
// destination as part of evaluation.
|
||||
static auto GetConstantValue(EvalContext& /*eval_context*/,
|
||||
|
||||
@@ -39,7 +39,7 @@ static auto WitnessAccessMatchesInterface(
|
||||
}
|
||||
|
||||
static auto IncompleteFacetTypeDiagnosticBuilder(
|
||||
Context& context, SemIRLoc loc, SemIR::InstId facet_type_inst_id,
|
||||
Context& context, SemIRLoc loc, SemIR::TypeInstId facet_type_inst_id,
|
||||
bool is_definition) -> DiagnosticBuilder {
|
||||
if (is_definition) {
|
||||
CARBON_DIAGNOSTIC(ImplAsIncompleteFacetTypeDefinition, Error,
|
||||
@@ -59,7 +59,7 @@ static auto IncompleteFacetTypeDiagnosticBuilder(
|
||||
|
||||
auto InitialFacetTypeImplWitness(
|
||||
Context& context, SemIR::LocId witness_loc_id,
|
||||
SemIR::InstId facet_type_inst_id, SemIR::InstId self_type_inst_id,
|
||||
SemIR::TypeInstId facet_type_inst_id, SemIR::TypeInstId self_type_inst_id,
|
||||
const SemIR::SpecificInterface& interface_to_witness,
|
||||
SemIR::SpecificId self_specific_id, bool is_definition) -> SemIR::InstId {
|
||||
// TODO: Finish facet type resolution. This code currently only handles
|
||||
@@ -233,8 +233,8 @@ auto InitialFacetTypeImplWitness(
|
||||
return witness_inst_id;
|
||||
}
|
||||
|
||||
auto RequireCompleteFacetTypeForImplDefinition(Context& context, SemIRLoc loc,
|
||||
SemIR::InstId facet_type_inst_id)
|
||||
auto RequireCompleteFacetTypeForImplDefinition(
|
||||
Context& context, SemIRLoc loc, SemIR::TypeInstId facet_type_inst_id)
|
||||
-> bool {
|
||||
auto facet_type_id =
|
||||
context.types().GetTypeIdForTypeInstId(facet_type_inst_id);
|
||||
|
||||
@@ -41,14 +41,14 @@ auto FacetTypeFromInterface(Context& context, SemIR::InterfaceId interface_id,
|
||||
// `Self` type.
|
||||
auto InitialFacetTypeImplWitness(
|
||||
Context& context, SemIR::LocId witness_loc_id,
|
||||
SemIR::InstId facet_type_inst_id, SemIR::InstId self_type_inst_id,
|
||||
SemIR::TypeInstId facet_type_inst_id, SemIR::TypeInstId self_type_inst_id,
|
||||
const SemIR::SpecificInterface& interface_to_witness,
|
||||
SemIR::SpecificId self_specific_id, bool is_definition) -> SemIR::InstId;
|
||||
|
||||
// Returns `true` if the facet type is complete. Otherwise issues a diagnostic
|
||||
// and returns `false`.
|
||||
auto RequireCompleteFacetTypeForImplDefinition(Context& context, SemIRLoc loc,
|
||||
SemIR::InstId facet_type_inst_id)
|
||||
auto RequireCompleteFacetTypeForImplDefinition(
|
||||
Context& context, SemIRLoc loc, SemIR::TypeInstId facet_type_inst_id)
|
||||
-> bool;
|
||||
|
||||
// Replaces the placeholder created by `InitialFacetTypeImplWitness` with an
|
||||
|
||||
@@ -143,7 +143,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
|
||||
cast_type_id);
|
||||
});
|
||||
if (cast_type_id == SemIR::ErrorInst::SingletonTypeId) {
|
||||
cast_type_inst_id = SemIR::ErrorInst::SingletonInstId;
|
||||
cast_type_inst_id = SemIR::ErrorInst::SingletonTypeInstId;
|
||||
}
|
||||
auto binding_id =
|
||||
context.parse_tree().As<Parse::VarBindingPatternId>(node_id);
|
||||
|
||||
@@ -370,7 +370,7 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto [adapted_inst_id, adapted_type_id] =
|
||||
auto [adapted_type_inst_id, adapted_type_id] =
|
||||
ExprAsType(context, node_id, adapted_type_expr_id);
|
||||
adapted_type_id = AsConcreteType(
|
||||
context, adapted_type_id, node_id,
|
||||
@@ -379,26 +379,26 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool {
|
||||
"adapted type {0} is an incomplete type",
|
||||
InstIdAsType);
|
||||
return context.emitter().Build(node_id, IncompleteTypeInAdaptDecl,
|
||||
adapted_inst_id);
|
||||
adapted_type_inst_id);
|
||||
},
|
||||
[&] {
|
||||
CARBON_DIAGNOSTIC(AbstractTypeInAdaptDecl, Error,
|
||||
"adapted type {0} is an abstract type", InstIdAsType);
|
||||
return context.emitter().Build(node_id, AbstractTypeInAdaptDecl,
|
||||
adapted_inst_id);
|
||||
adapted_type_inst_id);
|
||||
});
|
||||
if (adapted_type_id == SemIR::ErrorInst::SingletonTypeId) {
|
||||
adapted_inst_id = SemIR::ErrorInst::SingletonInstId;
|
||||
adapted_type_inst_id = SemIR::ErrorInst::SingletonTypeInstId;
|
||||
}
|
||||
|
||||
// Build a SemIR representation for the declaration.
|
||||
class_info.adapt_id = AddInst<SemIR::AdaptDecl>(
|
||||
context, node_id, {.adapted_type_inst_id = adapted_inst_id});
|
||||
context, node_id, {.adapted_type_inst_id = adapted_type_inst_id});
|
||||
|
||||
// Extend the class scope with the adapted type's scope if requested.
|
||||
if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
|
||||
auto& class_scope = context.name_scopes().Get(class_info.scope_id);
|
||||
class_scope.AddExtendedScope(adapted_inst_id);
|
||||
class_scope.AddExtendedScope(adapted_type_inst_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -422,17 +422,17 @@ struct BaseInfo {
|
||||
|
||||
SemIR::TypeId type_id;
|
||||
SemIR::NameScopeId scope_id;
|
||||
SemIR::InstId inst_id;
|
||||
SemIR::TypeInstId inst_id;
|
||||
};
|
||||
constexpr BaseInfo BaseInfo::Error = {
|
||||
.type_id = SemIR::ErrorInst::SingletonTypeId,
|
||||
.scope_id = SemIR::NameScopeId::None,
|
||||
.inst_id = SemIR::ErrorInst::SingletonInstId};
|
||||
.inst_id = SemIR::ErrorInst::SingletonTypeInstId};
|
||||
} // namespace
|
||||
|
||||
// Diagnoses an attempt to derive from a final type.
|
||||
static auto DiagnoseBaseIsFinal(Context& context, Parse::NodeId node_id,
|
||||
SemIR::InstId base_type_inst_id) -> void {
|
||||
SemIR::TypeInstId base_type_inst_id) -> void {
|
||||
CARBON_DIAGNOSTIC(BaseIsFinal, Error,
|
||||
"deriving from final type {0}; base type must be an "
|
||||
"`abstract` or `base` class",
|
||||
|
||||
@@ -53,7 +53,7 @@ auto HandleParseNode(Context& context, Parse::FunctionIntroducerId node_id)
|
||||
auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool {
|
||||
// Propagate the type expression.
|
||||
auto [type_node_id, type_inst_id] = context.node_stack().PopExprWithNodeId();
|
||||
auto type_id = ExprAsType(context, type_node_id, type_inst_id).type_id;
|
||||
auto as_type = ExprAsType(context, type_node_id, type_inst_id);
|
||||
|
||||
// If the previous node was `IdentifierNameBeforeParams`, then it would have
|
||||
// caused these entries to be pushed to the pattern stacks. But it's possible
|
||||
@@ -69,10 +69,11 @@ auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool {
|
||||
}
|
||||
|
||||
auto return_slot_pattern_id = AddPatternInst<SemIR::ReturnSlotPattern>(
|
||||
context, node_id, {.type_id = type_id, .type_inst_id = type_inst_id});
|
||||
context, node_id,
|
||||
{.type_id = as_type.type_id, .type_inst_id = as_type.inst_id});
|
||||
auto param_pattern_id = AddPatternInst<SemIR::OutParamPattern>(
|
||||
context, node_id,
|
||||
{.type_id = type_id,
|
||||
{.type_id = as_type.type_id,
|
||||
.subpattern_id = return_slot_pattern_id,
|
||||
.index = SemIR::CallParamIndex::None});
|
||||
context.node_stack().Push(node_id, param_pattern_id);
|
||||
|
||||
@@ -55,14 +55,14 @@ auto HandleParseNode(Context& context, Parse::ForallId /*node_id*/) -> bool {
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::TypeImplAsId node_id) -> bool {
|
||||
auto [self_node, self_id] = context.node_stack().PopExprWithNodeId();
|
||||
self_id = ExprAsType(context, self_node, self_id).inst_id;
|
||||
context.node_stack().Push(node_id, self_id);
|
||||
auto self_type_inst_id = ExprAsType(context, self_node, self_id).inst_id;
|
||||
context.node_stack().Push(node_id, self_type_inst_id);
|
||||
|
||||
// Introduce `Self`. Note that we add this name lexically rather than adding
|
||||
// to the `NameScopeId` of the `impl`, because this happens before we enter
|
||||
// the `impl` scope or even identify which `impl` we're declaring.
|
||||
// TODO: Revisit this once #3714 is resolved.
|
||||
AddNameToLookup(context, SemIR::NameId::SelfType, self_id);
|
||||
AddNameToLookup(context, SemIR::NameId::SelfType, self_type_inst_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -109,11 +109,11 @@ auto HandleParseNode(Context& context, Parse::DefaultSelfImplAsId node_id)
|
||||
// is a class and found its `Self`, so additionally performing an unqualified
|
||||
// name lookup would be redundant work, but would avoid duplicating the
|
||||
// handling of the `Self` expression.
|
||||
auto self_inst_id = AddInst(
|
||||
auto self_inst_id = context.types().GetAsTypeInstId(AddInst(
|
||||
context, node_id,
|
||||
SemIR::NameRef{.type_id = SemIR::TypeType::SingletonTypeId,
|
||||
.name_id = SemIR::NameId::SelfType,
|
||||
.value_id = context.types().GetInstId(self_type_id)});
|
||||
.value_id = context.types().GetInstId(self_type_id)}));
|
||||
|
||||
// There's no need to push `Self` into scope here, because we can find it in
|
||||
// the parent class scope.
|
||||
@@ -135,8 +135,8 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
|
||||
Parse::AnyImplDeclId node_id, SemIR::ImplId impl_id,
|
||||
Parse::NodeId self_type_node, SemIR::TypeId self_type_id,
|
||||
Parse::NodeId params_node,
|
||||
SemIR::InstId constraint_inst_id,
|
||||
SemIR::TypeId constraint_id) -> bool {
|
||||
SemIR::TypeInstId constraint_type_inst_id,
|
||||
SemIR::TypeId constraint_type_id) -> bool {
|
||||
auto parent_scope_id = context.decl_name_stack().PeekParentScopeId();
|
||||
if (!parent_scope_id.has_value()) {
|
||||
DiagnoseExtendImplOutsideClass(context, node_id);
|
||||
@@ -188,14 +188,14 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
|
||||
parent_scope.set_has_error();
|
||||
} else {
|
||||
bool is_complete = RequireCompleteType(
|
||||
context, constraint_id, context.insts().GetLocId(constraint_inst_id),
|
||||
[&] {
|
||||
context, constraint_type_id,
|
||||
context.insts().GetLocId(constraint_type_inst_id), [&] {
|
||||
CARBON_DIAGNOSTIC(ExtendImplAsIncomplete, Error,
|
||||
"`extend impl as` incomplete facet type {0}",
|
||||
InstIdAsType);
|
||||
return context.emitter().Build(impl.latest_decl_id(),
|
||||
ExtendImplAsIncomplete,
|
||||
constraint_inst_id);
|
||||
constraint_type_inst_id);
|
||||
});
|
||||
if (!is_complete) {
|
||||
parent_scope.set_has_error();
|
||||
@@ -203,7 +203,7 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
|
||||
}
|
||||
}
|
||||
|
||||
parent_scope.AddExtendedScope(constraint_inst_id);
|
||||
parent_scope.AddExtendedScope(constraint_type_inst_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ static auto IsValidImplRedecl(Context& context, SemIR::Impl& new_impl,
|
||||
// and returns `None`.
|
||||
static auto CheckConstraintIsInterface(Context& context,
|
||||
SemIR::InstId impl_decl_id,
|
||||
SemIR::InstId constraint_id)
|
||||
SemIR::TypeInstId constraint_id)
|
||||
-> SemIR::SpecificInterface {
|
||||
auto facet_type_id = context.types().GetTypeIdForTypeInstId(constraint_id);
|
||||
if (facet_type_id == SemIR::ErrorInst::SingletonTypeId) {
|
||||
@@ -351,15 +351,15 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
|
||||
-> std::pair<SemIR::ImplId, SemIR::InstId> {
|
||||
auto [constraint_node, constraint_id] =
|
||||
context.node_stack().PopExprWithNodeId();
|
||||
auto [self_type_node, self_inst_id] =
|
||||
auto [self_type_node, self_type_inst_id] =
|
||||
context.node_stack().PopWithNodeId<Parse::NodeCategory::ImplAs>();
|
||||
auto self_type_id = context.types().GetTypeIdForTypeInstId(self_inst_id);
|
||||
auto self_type_id = context.types().GetTypeIdForTypeInstId(self_type_inst_id);
|
||||
// Pop the `impl` introducer and any `forall` parameters as a "name".
|
||||
auto name = PopImplIntroducerAndParamsAsNameComponent(context, node_id);
|
||||
auto decl_block_id = context.inst_block_stack().Pop();
|
||||
|
||||
// Convert the constraint expression to a type.
|
||||
auto [constraint_inst_id, constraint_type_id] =
|
||||
auto [constraint_type_inst_id, constraint_type_id] =
|
||||
ExprAsType(context, constraint_node, constraint_id);
|
||||
|
||||
// Process modifiers.
|
||||
@@ -385,10 +385,10 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
|
||||
SemIR::Impl impl_info = {name_context.MakeEntityWithParamsBase(
|
||||
name, impl_decl_id,
|
||||
/*is_extern=*/false, SemIR::LibraryNameId::None),
|
||||
{.self_id = self_inst_id,
|
||||
.constraint_id = constraint_inst_id,
|
||||
{.self_id = self_type_inst_id,
|
||||
.constraint_id = constraint_type_inst_id,
|
||||
.interface = CheckConstraintIsInterface(
|
||||
context, impl_decl_id, constraint_inst_id),
|
||||
context, impl_decl_id, constraint_type_inst_id),
|
||||
.is_final = is_final}};
|
||||
// Add the impl declaration.
|
||||
bool invalid_redeclaration = false;
|
||||
@@ -486,17 +486,17 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
|
||||
introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
|
||||
auto extend_node = introducer.modifier_node_id(ModifierOrder::Decl);
|
||||
if (impl_info.generic_id.has_value()) {
|
||||
SemIR::TypeId type_id = context.insts().Get(constraint_inst_id).type_id();
|
||||
constraint_inst_id = AddInst<SemIR::SpecificConstant>(
|
||||
context, context.insts().GetLocId(constraint_inst_id),
|
||||
{.type_id = type_id,
|
||||
.inst_id = constraint_inst_id,
|
||||
.specific_id =
|
||||
context.generics().GetSelfSpecific(impl_info.generic_id)});
|
||||
constraint_type_inst_id =
|
||||
context.types().GetAsTypeInstId(AddInst<SemIR::SpecificConstant>(
|
||||
context, context.insts().GetLocId(constraint_type_inst_id),
|
||||
{.type_id = SemIR::TypeType::SingletonTypeId,
|
||||
.inst_id = constraint_type_inst_id,
|
||||
.specific_id =
|
||||
context.generics().GetSelfSpecific(impl_info.generic_id)}));
|
||||
}
|
||||
if (!ExtendImpl(context, extend_node, node_id, impl_decl.impl_id,
|
||||
self_type_node, self_type_id, name.implicit_params_loc_id,
|
||||
constraint_inst_id, constraint_type_id)) {
|
||||
constraint_type_inst_id, constraint_type_id)) {
|
||||
// Don't allow the invalid impl to be used.
|
||||
FillImplWitnessWithErrors(context, impl_info);
|
||||
context.impls().Get(impl_decl.impl_id).witness_id =
|
||||
|
||||
@@ -111,7 +111,7 @@ auto HandleParseNode(Context& context, Parse::RequirementImplsId node_id)
|
||||
ImplsOnNonFacetType, Error,
|
||||
"right argument of `impls` requirement must be a facet type");
|
||||
context.emitter().Emit(rhs_node, ImplsOnNonFacetType);
|
||||
rhs_as_type.inst_id = SemIR::ErrorInst::SingletonInstId;
|
||||
rhs_as_type.inst_id = SemIR::ErrorInst::SingletonTypeInstId;
|
||||
}
|
||||
// TODO: Require that at least one side uses a designator.
|
||||
// TODO: For things like `HashSet(.T) as type`, add an implied constraint
|
||||
|
||||
@@ -80,6 +80,12 @@ static auto FindAssociatedImportIRs(Context& context,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::TypeInstId inst_id): {
|
||||
if (inst_id.has_value()) {
|
||||
worklist.push_back(inst_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::InstBlockId inst_block_id): {
|
||||
push_block(inst_block_id);
|
||||
break;
|
||||
|
||||
@@ -272,7 +272,7 @@ static auto MapType(Context& context, clang::QualType type) -> TypeExpr {
|
||||
context.ast_context().getTypeSize(type) == 32) {
|
||||
return MakeIntType(context, context.ints().Add(32));
|
||||
}
|
||||
return {.inst_id = SemIR::ErrorInst::SingletonInstId,
|
||||
return {.inst_id = SemIR::ErrorInst::SingletonTypeInstId,
|
||||
.type_id = SemIR::ErrorInst::SingletonTypeId};
|
||||
}
|
||||
|
||||
|
||||
@@ -699,6 +699,15 @@ static auto GetLocalConstantInstId(ImportRefResolver& resolver,
|
||||
return resolver.local_constant_values().GetInstIdIfValid(const_id);
|
||||
}
|
||||
|
||||
// Returns the local constant InstId for an imported InstId.
|
||||
static auto GetLocalTypeInstId(ImportRefResolver& resolver,
|
||||
SemIR::TypeInstId inst_id) -> SemIR::TypeInstId {
|
||||
// The input instruction is a TypeInstId, and import does not change the type
|
||||
// of instructions, so the result is also a valid TypeInstId.
|
||||
return SemIR::TypeInstId::UnsafeMake(
|
||||
GetLocalConstantInstId(resolver, static_cast<SemIR::InstId>(inst_id)));
|
||||
}
|
||||
|
||||
// Returns the ConstantId for a TypeId. Adds unresolved constants to
|
||||
// work_stack_.
|
||||
static auto GetLocalConstantId(ImportRefResolver& resolver,
|
||||
@@ -1165,7 +1174,7 @@ static auto GetLocalReturnSlotPatternId(
|
||||
MakeImportedLocIdAndInst<SemIR::ReturnSlotPattern>(
|
||||
context.local_context(),
|
||||
AddImportIRInst(context, param_pattern.subpattern_id),
|
||||
{.type_id = type_id, .type_inst_id = SemIR::InstId::None}));
|
||||
{.type_id = type_id, .type_inst_id = SemIR::TypeInstId::None}));
|
||||
return AddInstInNoBlock(
|
||||
context.local_context(),
|
||||
MakeImportedLocIdAndInst<SemIR::OutParamPattern>(
|
||||
@@ -1400,9 +1409,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
|
||||
auto adapted_type_inst_id =
|
||||
auto adapted_type_inst_id = resolver.local_ir().types().GetAsTypeInstId(
|
||||
AddLoadedImportRef(resolver, SemIR::TypeType::SingletonTypeId,
|
||||
inst.adapted_type_inst_id, adapted_type_const_id);
|
||||
inst.adapted_type_inst_id, adapted_type_const_id));
|
||||
|
||||
// Create a corresponding instruction to represent the declaration.
|
||||
auto inst_id = AddInstInNoBlock(
|
||||
@@ -1418,7 +1427,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
SemIR::ArrayType inst) -> ResolveResult {
|
||||
CARBON_CHECK(inst.type_id == SemIR::TypeType::SingletonTypeId);
|
||||
auto element_type_inst_id =
|
||||
GetLocalConstantInstId(resolver, inst.element_type_inst_id);
|
||||
GetLocalTypeInstId(resolver, inst.element_type_inst_id);
|
||||
auto bound_id = GetLocalConstantInstId(resolver, inst.bound_id);
|
||||
if (resolver.HasNewWork()) {
|
||||
return ResolveResult::Retry();
|
||||
@@ -1559,9 +1568,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
|
||||
auto base_type_inst_id =
|
||||
auto base_type_inst_id = resolver.local_ir().types().GetAsTypeInstId(
|
||||
AddLoadedImportRef(resolver, SemIR::TypeType::SingletonTypeId,
|
||||
inst.base_type_inst_id, base_type_const_id);
|
||||
inst.base_type_inst_id, base_type_const_id));
|
||||
|
||||
// Create a corresponding instruction to represent the declaration.
|
||||
auto inst_id = AddInstInNoBlock(
|
||||
@@ -2130,8 +2139,8 @@ static auto MakeImplDeclaration(ImportContext& context,
|
||||
AddImportIRInst(context, import_impl.latest_decl_id()), impl_decl));
|
||||
impl_decl.impl_id = context.local_impls().Add(
|
||||
{GetIncompleteLocalEntityBase(context, impl_decl_id, import_impl),
|
||||
{.self_id = SemIR::InstId::None,
|
||||
.constraint_id = SemIR::InstId::None,
|
||||
{.self_id = SemIR::TypeInstId::None,
|
||||
.constraint_id = SemIR::TypeInstId::None,
|
||||
.interface = SemIR::SpecificInterface::None,
|
||||
.witness_id = witness_id}});
|
||||
|
||||
@@ -2226,12 +2235,12 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
|
||||
// Create instructions for self and constraint to hold the symbolic constant
|
||||
// value for a generic impl.
|
||||
new_impl.self_id =
|
||||
new_impl.self_id = resolver.local_ir().types().GetAsTypeInstId(
|
||||
AddLoadedImportRef(resolver, SemIR::TypeType::SingletonTypeId,
|
||||
import_impl.self_id, self_const_id);
|
||||
new_impl.constraint_id =
|
||||
import_impl.self_id, self_const_id));
|
||||
new_impl.constraint_id = resolver.local_ir().types().GetAsTypeInstId(
|
||||
AddLoadedImportRef(resolver, SemIR::TypeType::SingletonTypeId,
|
||||
import_impl.constraint_id, constraint_const_id);
|
||||
import_impl.constraint_id, constraint_const_id));
|
||||
new_impl.interface = GetLocalSpecificInterface(
|
||||
resolver, import_impl.interface, specific_interface_data);
|
||||
if (import_impl.is_complete()) {
|
||||
@@ -2499,7 +2508,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
SemIR::FacetValue inst) -> ResolveResult {
|
||||
auto type_id = GetLocalConstantId(resolver, inst.type_id);
|
||||
auto type_inst_id = GetLocalConstantInstId(resolver, inst.type_inst_id);
|
||||
auto type_inst_id = GetLocalTypeInstId(resolver, inst.type_inst_id);
|
||||
auto witnesses = GetLocalInstBlockContents(resolver, inst.witnesses_block_id);
|
||||
if (resolver.HasNewWork()) {
|
||||
return ResolveResult::Retry();
|
||||
@@ -2808,9 +2817,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
-> ResolveResult {
|
||||
CARBON_CHECK(inst.type_id == SemIR::TypeType::SingletonTypeId);
|
||||
auto class_const_inst_id =
|
||||
GetLocalConstantInstId(resolver, inst.class_type_inst_id);
|
||||
GetLocalTypeInstId(resolver, inst.class_type_inst_id);
|
||||
auto elem_const_inst_id =
|
||||
GetLocalConstantInstId(resolver, inst.element_type_inst_id);
|
||||
GetLocalTypeInstId(resolver, inst.element_type_inst_id);
|
||||
if (resolver.HasNewWork()) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ class NodeStack {
|
||||
Parse::NodeCategory::MemberName | Parse::NodeCategory::NonExprName,
|
||||
Id::KindFor<SemIR::NameId>());
|
||||
set_id_if_category_is(Parse::NodeCategory::ImplAs,
|
||||
Id::KindFor<SemIR::InstId>());
|
||||
Id::KindFor<SemIR::TypeInstId>());
|
||||
set_id_if_category_is(Parse::NodeCategory::Decl |
|
||||
Parse::NodeCategory::Statement |
|
||||
Parse::NodeCategory::Modifier,
|
||||
|
||||
@@ -89,6 +89,12 @@ static auto PushOperand(Context& context, Worklist& worklist,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::TypeInstId inst_id): {
|
||||
if (inst_id.has_value()) {
|
||||
worklist.Push(inst_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::InstBlockId inst_block_id): {
|
||||
push_block(inst_block_id);
|
||||
break;
|
||||
@@ -175,6 +181,12 @@ static auto PopOperand(Context& context, Worklist& worklist,
|
||||
}
|
||||
return worklist.Pop().index;
|
||||
}
|
||||
case CARBON_KIND(SemIR::TypeInstId inst_id): {
|
||||
if (!inst_id.has_value()) {
|
||||
return arg.value();
|
||||
}
|
||||
return worklist.Pop().index;
|
||||
}
|
||||
case CARBON_KIND(SemIR::InstBlockId inst_block_id): {
|
||||
return pop_block_id(inst_block_id).index;
|
||||
}
|
||||
|
||||
@@ -157,8 +157,8 @@ auto GetPointerType(Context& context, SemIR::InstId pointee_type_id)
|
||||
return GetTypeImpl<SemIR::PointerType>(context, pointee_type_id);
|
||||
}
|
||||
|
||||
auto GetUnboundElementType(Context& context, SemIR::InstId class_type_id,
|
||||
SemIR::InstId element_type_id) -> SemIR::TypeId {
|
||||
auto GetUnboundElementType(Context& context, SemIR::TypeInstId class_type_id,
|
||||
SemIR::TypeInstId element_type_id) -> SemIR::TypeId {
|
||||
return GetTypeImpl<SemIR::UnboundElementType>(context, class_type_id,
|
||||
element_type_id);
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ auto GetTupleType(Context& context, llvm::ArrayRef<SemIR::InstId> type_inst_ids)
|
||||
-> SemIR::TypeId;
|
||||
|
||||
// Returns an unbound element type.
|
||||
auto GetUnboundElementType(Context& context, SemIR::InstId class_type_id,
|
||||
SemIR::InstId element_type_id) -> SemIR::TypeId;
|
||||
auto GetUnboundElementType(Context& context, SemIR::TypeInstId class_type_id,
|
||||
SemIR::TypeInstId element_type_id) -> SemIR::TypeId;
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
|
||||
@@ -63,12 +63,12 @@ fn Foo(n: ()) -> ((), ()) {
|
||||
// CHECK:STDOUT: inst25: {kind: Converted, arg0: inst21, arg1: inst15, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst26: {kind: Converted, arg0: inst22, arg1: inst15, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst27: {kind: Converted, arg0: inst24, arg1: inst23, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst28: {kind: ReturnSlotPattern, arg0: inst24, type: type(inst23)}
|
||||
// CHECK:STDOUT: inst28: {kind: ReturnSlotPattern, arg0: inst27, type: type(inst23)}
|
||||
// CHECK:STDOUT: inst29: {kind: OutParamPattern, arg0: inst28, arg1: call_param1, type: type(inst23)}
|
||||
// CHECK:STDOUT: inst30: {kind: ValueParam, arg0: call_param0, arg1: name1, type: type(inst15)}
|
||||
// CHECK:STDOUT: inst31: {kind: SpliceBlock, arg0: inst_block4, arg1: inst17, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst32: {kind: OutParam, arg0: call_param1, arg1: name(ReturnSlot), type: type(inst23)}
|
||||
// CHECK:STDOUT: inst33: {kind: ReturnSlot, arg0: inst24, arg1: inst32, type: type(inst23)}
|
||||
// CHECK:STDOUT: inst33: {kind: ReturnSlot, arg0: inst27, arg1: inst32, type: type(inst23)}
|
||||
// CHECK:STDOUT: inst34: {kind: FunctionDecl, arg0: function0, arg1: inst_block11, type: type(inst35)}
|
||||
// CHECK:STDOUT: inst35: {kind: FunctionType, arg0: function0, arg1: specific<none>, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst36: {kind: StructValue, arg0: inst_block_empty, type: type(inst35)}
|
||||
|
||||
+2
-2
@@ -77,11 +77,11 @@ fn Foo[T:! type](n: T) -> (T, ()) {
|
||||
// CHECK:STDOUT: inst28: {kind: Converted, arg0: inst25, arg1: inst24, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst29: {kind: TupleType, arg0: inst_block11, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst30: {kind: Converted, arg0: inst27, arg1: inst29, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst31: {kind: ReturnSlotPattern, arg0: inst27, type: type(symbolic_constant5)}
|
||||
// CHECK:STDOUT: inst31: {kind: ReturnSlotPattern, arg0: inst30, type: type(symbolic_constant5)}
|
||||
// CHECK:STDOUT: inst32: {kind: OutParamPattern, arg0: inst31, arg1: call_param1, type: type(symbolic_constant5)}
|
||||
// CHECK:STDOUT: inst33: {kind: ValueParam, arg0: call_param0, arg1: name2, type: type(symbolic_constant3)}
|
||||
// CHECK:STDOUT: inst34: {kind: OutParam, arg0: call_param1, arg1: name(ReturnSlot), type: type(symbolic_constant5)}
|
||||
// CHECK:STDOUT: inst35: {kind: ReturnSlot, arg0: inst27, arg1: inst34, type: type(symbolic_constant5)}
|
||||
// CHECK:STDOUT: inst35: {kind: ReturnSlot, arg0: inst30, arg1: inst34, type: type(symbolic_constant5)}
|
||||
// CHECK:STDOUT: inst36: {kind: FunctionDecl, arg0: function0, arg1: inst_block14, type: type(inst40)}
|
||||
// CHECK:STDOUT: inst37: {kind: BindSymbolicName, arg0: entity_name0, arg1: inst<none>, type: type(TypeType)}
|
||||
// CHECK:STDOUT: inst38: {kind: SymbolicBindingPattern, arg0: entity_name0, type: type(TypeType)}
|
||||
|
||||
@@ -1398,6 +1398,10 @@ class FormatterImpl {
|
||||
}
|
||||
}
|
||||
|
||||
auto FormatName(TypeInstId id) -> void {
|
||||
FormatName(static_cast<InstId>(id));
|
||||
}
|
||||
|
||||
auto FormatLabel(InstBlockId id) -> void {
|
||||
out_ << inst_namer_->GetLabelFor(scope_, id);
|
||||
}
|
||||
|
||||
@@ -179,7 +179,8 @@ using IdKind = TypeEnum<
|
||||
NameScopeId,
|
||||
SpecificId,
|
||||
SpecificInterfaceId,
|
||||
StructTypeFieldsId>;
|
||||
StructTypeFieldsId,
|
||||
TypeInstId>;
|
||||
// clang-format on
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
@@ -52,6 +52,26 @@ struct InstId : public IdBase<InstId> {
|
||||
|
||||
constexpr InstId InstId::InitTombstone = InstId(NoneIndex - 1);
|
||||
|
||||
// And InstId whose value is a type. The fact it's a type is CHECKed on
|
||||
// construction, and this allows that check to be represented in the type
|
||||
// system.
|
||||
struct TypeInstId : public InstId {
|
||||
static const TypeInstId None;
|
||||
|
||||
using InstId::InstId;
|
||||
|
||||
static constexpr auto UnsafeMake(InstId id) -> TypeInstId {
|
||||
return TypeInstId(UnsafeCtor(), id);
|
||||
}
|
||||
|
||||
private:
|
||||
struct UnsafeCtor {};
|
||||
explicit constexpr TypeInstId(UnsafeCtor /*unsafe*/, InstId id)
|
||||
: InstId(id) {}
|
||||
};
|
||||
|
||||
constexpr TypeInstId TypeInstId::None = TypeInstId::UnsafeMake(InstId::None);
|
||||
|
||||
// An ID of an instruction that is referenced absolutely by another instruction.
|
||||
// This should only be used as the type of a field within a typed instruction
|
||||
// class.
|
||||
|
||||
@@ -17,9 +17,9 @@ struct ImplFields {
|
||||
// This following members always have values and do not change.
|
||||
|
||||
// The type for which the impl is implementing a constraint.
|
||||
InstId self_id;
|
||||
TypeInstId self_id;
|
||||
// The constraint that the impl implements.
|
||||
InstId constraint_id;
|
||||
TypeInstId constraint_id;
|
||||
|
||||
// The single interface to implement from `constraint_id`.
|
||||
// The members are `None` if `constraint_id` isn't complete or doesn't
|
||||
|
||||
+32
-15
@@ -8,28 +8,45 @@
|
||||
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
auto TypeStore::GetTypeIdForTypeConstantId(SemIR::ConstantId constant_id) const
|
||||
-> SemIR::TypeId {
|
||||
// Verify that the constant value's type is `TypeType` (or an error).
|
||||
static void CheckTypeOfConstantIsTypeType(File& file, ConstantId constant_id) {
|
||||
CARBON_CHECK(constant_id.is_constant(),
|
||||
"Canonicalizing non-constant type: {0}", constant_id);
|
||||
auto type_id = file_->insts()
|
||||
.Get(file_->constant_values().GetInstId(constant_id))
|
||||
.type_id();
|
||||
CARBON_CHECK(type_id == SemIR::TypeType::SingletonTypeId ||
|
||||
constant_id == SemIR::ErrorInst::SingletonConstantId,
|
||||
auto type_id =
|
||||
file.insts().Get(file.constant_values().GetInstId(constant_id)).type_id();
|
||||
CARBON_CHECK(type_id == TypeType::SingletonTypeId ||
|
||||
constant_id == ErrorInst::SingletonConstantId,
|
||||
"Forming type ID for non-type constant of type {0}",
|
||||
GetAsInst(type_id));
|
||||
|
||||
return SemIR::TypeId::ForTypeConstant(constant_id);
|
||||
file.types().GetAsInst(type_id));
|
||||
}
|
||||
|
||||
auto TypeStore::GetTypeIdForTypeInstId(SemIR::InstId inst_id) const
|
||||
-> SemIR::TypeId {
|
||||
return GetTypeIdForTypeConstantId(file_->constant_values().Get(inst_id));
|
||||
auto TypeStore::GetTypeIdForTypeConstantId(ConstantId constant_id) const
|
||||
-> TypeId {
|
||||
CheckTypeOfConstantIsTypeType(*file_, constant_id);
|
||||
return TypeId::ForTypeConstant(constant_id);
|
||||
}
|
||||
|
||||
auto TypeStore::GetInstId(TypeId type_id) const -> InstId {
|
||||
return file_->constant_values().GetInstId(GetConstantId(type_id));
|
||||
auto TypeStore::GetTypeIdForTypeInstId(InstId inst_id) const -> TypeId {
|
||||
auto constant_id = file_->constant_values().Get(inst_id);
|
||||
CheckTypeOfConstantIsTypeType(*file_, constant_id);
|
||||
return TypeId::ForTypeConstant(constant_id);
|
||||
}
|
||||
|
||||
auto TypeStore::GetTypeIdForTypeInstId(TypeInstId inst_id) const -> TypeId {
|
||||
auto constant_id = file_->constant_values().Get(inst_id);
|
||||
return TypeId::ForTypeConstant(constant_id);
|
||||
}
|
||||
|
||||
auto TypeStore::GetAsTypeInstId(InstId inst_id) const -> TypeInstId {
|
||||
auto constant_id = file_->constant_values().Get(inst_id);
|
||||
CheckTypeOfConstantIsTypeType(*file_, constant_id);
|
||||
return TypeInstId::UnsafeMake(inst_id);
|
||||
}
|
||||
|
||||
auto TypeStore::GetInstId(TypeId type_id) const -> TypeInstId {
|
||||
// The instruction for a TypeId has a value of that TypeId.
|
||||
return TypeInstId::UnsafeMake(
|
||||
file_->constant_values().GetInstId(GetConstantId(type_id)));
|
||||
}
|
||||
|
||||
auto TypeStore::GetAsInst(TypeId type_id) const -> Inst {
|
||||
|
||||
@@ -39,8 +39,7 @@ class TypeStore : public Yaml::Printable<TypeStore> {
|
||||
// Facet values are of the same typishness as types, but are not themselves
|
||||
// types, so they can not be passed here. They should be converted to a type
|
||||
// through an `as type` conversion, that is, to a value of type `TypeType`.
|
||||
auto GetTypeIdForTypeConstantId(SemIR::ConstantId constant_id) const
|
||||
-> SemIR::TypeId;
|
||||
auto GetTypeIdForTypeConstantId(ConstantId constant_id) const -> TypeId;
|
||||
|
||||
// Returns the type ID for an instruction whose constant value is a type
|
||||
// value, i.e. it is a value of type `TypeType`.
|
||||
@@ -50,10 +49,16 @@ class TypeStore : public Yaml::Printable<TypeStore> {
|
||||
// so they can not be passed here. They should be converted to a type through
|
||||
// an `as type` conversion, such as to a `FacetAccessType` instruction whose
|
||||
// value is of type `TypeType`.
|
||||
auto GetTypeIdForTypeInstId(SemIR::InstId inst_id) const -> SemIR::TypeId;
|
||||
auto GetTypeIdForTypeInstId(InstId inst_id) const -> TypeId;
|
||||
auto GetTypeIdForTypeInstId(TypeInstId inst_id) const -> TypeId;
|
||||
|
||||
// Converts an `InstId` to a `TypeInstId` of the same id value. This process
|
||||
// involves checking that the type of the instruction's value is `TypeType`,
|
||||
// and then this check is encoded in the type system via `TypeInstId`.
|
||||
auto GetAsTypeInstId(InstId inst_id) const -> TypeInstId;
|
||||
|
||||
// Returns the ID of the instruction used to define the specified type.
|
||||
auto GetInstId(TypeId type_id) const -> InstId;
|
||||
auto GetInstId(TypeId type_id) const -> TypeInstId;
|
||||
|
||||
// Returns the instruction used to define the specified type.
|
||||
auto GetAsInst(TypeId type_id) const -> Inst;
|
||||
|
||||
@@ -81,7 +81,7 @@ struct AnyFoundationDecl {
|
||||
static constexpr InstKind Kinds[] = {InstKind::AdaptDecl, InstKind::BaseDecl};
|
||||
|
||||
InstKind kind;
|
||||
InstId foundation_type_inst_id;
|
||||
TypeInstId foundation_type_inst_id;
|
||||
// Kind-specific data.
|
||||
AnyRawId arg1;
|
||||
};
|
||||
@@ -94,7 +94,7 @@ struct AdaptDecl {
|
||||
.is_lowered = false});
|
||||
|
||||
// No type_id; this is not a value.
|
||||
InstId adapted_type_inst_id;
|
||||
TypeInstId adapted_type_inst_id;
|
||||
};
|
||||
|
||||
// Takes the address of a reference expression, such as for the `&` address-of
|
||||
@@ -193,7 +193,7 @@ struct ArrayType {
|
||||
|
||||
TypeId type_id;
|
||||
InstId bound_id;
|
||||
InstId element_type_inst_id;
|
||||
TypeInstId element_type_inst_id;
|
||||
};
|
||||
|
||||
// Perform a no-op conversion to a compatible type.
|
||||
@@ -287,7 +287,7 @@ struct BaseDecl {
|
||||
{.ir_name = "base_decl", .constant_kind = InstConstantKind::Unique});
|
||||
|
||||
TypeId type_id;
|
||||
InstId base_type_inst_id;
|
||||
TypeInstId base_type_inst_id;
|
||||
ElementIndex index;
|
||||
};
|
||||
|
||||
@@ -665,6 +665,8 @@ struct ErrorInst {
|
||||
ConstantId::ForConcreteConstant(SingletonInstId);
|
||||
static constexpr auto SingletonTypeId =
|
||||
TypeId::ForTypeConstant(SingletonConstantId);
|
||||
static constexpr auto SingletonTypeInstId =
|
||||
TypeInstId::UnsafeMake(SingletonInstId);
|
||||
|
||||
TypeId type_id;
|
||||
};
|
||||
@@ -736,7 +738,7 @@ struct FacetValue {
|
||||
// A `FacetType`.
|
||||
TypeId type_id;
|
||||
// The type that you will get if you cast this value to `type`.
|
||||
InstId type_inst_id;
|
||||
TypeInstId type_inst_id;
|
||||
// The set of `ImplWitness` instructions for a `FacetType`. The witnesses are
|
||||
// in the same order as the set of `required_interfaces` in the
|
||||
// `IdentifiedFacetType` of the `FacetType` from `type_id`, so that an index
|
||||
@@ -1387,7 +1389,7 @@ struct ReturnSlot {
|
||||
// The function return type as originally written by the user. For diagnostics
|
||||
// only; this has no semantic significance, and is not preserved across
|
||||
// imports.
|
||||
InstId type_inst_id;
|
||||
TypeInstId type_inst_id;
|
||||
|
||||
// The storage that will be initialized by the function.
|
||||
InstId storage_id;
|
||||
@@ -1410,7 +1412,7 @@ struct ReturnSlotPattern {
|
||||
// The function return type as originally written by the user. For diagnostics
|
||||
// only; this has no semantic significance, and is not preserved across
|
||||
// imports.
|
||||
InstId type_inst_id;
|
||||
TypeInstId type_inst_id;
|
||||
};
|
||||
|
||||
// An `expr == expr` clause in a `where` expression or `require` declaration.
|
||||
@@ -1782,9 +1784,9 @@ struct UnboundElementType {
|
||||
|
||||
TypeId type_id;
|
||||
// The `ClassType` that a value of this type is an element of.
|
||||
InstId class_type_inst_id;
|
||||
TypeInstId class_type_inst_id;
|
||||
// The type of the element.
|
||||
InstId element_type_inst_id;
|
||||
TypeInstId element_type_inst_id;
|
||||
};
|
||||
|
||||
// Converts from a value expression to an ephemeral reference expression, in
|
||||
|
||||
Reference in New Issue
Block a user