mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-03 13:35:58 +01:00
Move None to IdBase (#5030)
Use CRTP to eliminate per-type declarations of `None`. Note this adds `None` to a few that may not need it, but eliminates a lot off boilerplate. Note this leaves `GenericInstIndex::None` because it has a more complex construction. Also fix `InstId::InitTombstone` to be `NoneIndex - 1`
This commit is contained in:
@@ -48,6 +48,13 @@ template <typename IdT>
|
||||
struct IdBase : public AnyIdBase, public Printable<IdT> {
|
||||
using AnyIdBase::AnyIdBase;
|
||||
|
||||
// Provide a standard `None` mapping to `NoneIndex`.
|
||||
//
|
||||
// This uses a `&` to trigger slightly different instantiation behaviors in
|
||||
// Clang. For context on why this is needed, see http://wg21.link/CWG2800.
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
static const IdT& None;
|
||||
|
||||
auto Print(llvm::raw_ostream& out) const -> void {
|
||||
out << IdT::Label;
|
||||
if (has_value()) {
|
||||
@@ -63,6 +70,9 @@ struct IdBase : public AnyIdBase, public Printable<IdT> {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IdT>
|
||||
constexpr const IdT& IdBase<IdT>::None = IdT(NoneIndex);
|
||||
|
||||
// A lightweight handle to an item that behaves like an index.
|
||||
//
|
||||
// Unlike IdBase, classes derived from IndexBase are not completely opaque, and
|
||||
|
||||
@@ -20,13 +20,11 @@ namespace Carbon::Check {
|
||||
struct ScopeIndex : public IndexBase<ScopeIndex> {
|
||||
static constexpr llvm::StringLiteral Label = "scope";
|
||||
static const ScopeIndex Package;
|
||||
static const ScopeIndex None;
|
||||
|
||||
using IndexBase::IndexBase;
|
||||
};
|
||||
|
||||
constexpr ScopeIndex ScopeIndex::Package = ScopeIndex(0);
|
||||
constexpr ScopeIndex ScopeIndex::None = ScopeIndex(NoneIndex);
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
|
||||
@@ -29,14 +29,9 @@ struct DeferredDefinitionIndex : public IndexBase<DeferredDefinitionIndex> {
|
||||
static constexpr llvm::StringLiteral Label = "deferred_def";
|
||||
using ValueType = DeferredDefinition;
|
||||
|
||||
static const DeferredDefinitionIndex None;
|
||||
|
||||
using IndexBase::IndexBase;
|
||||
};
|
||||
|
||||
constexpr DeferredDefinitionIndex DeferredDefinitionIndex::None =
|
||||
DeferredDefinitionIndex(NoneIndex);
|
||||
|
||||
// A function whose definition is deferred because it is defined inline in a
|
||||
// class or similar scope.
|
||||
//
|
||||
|
||||
+1
-131
@@ -40,9 +40,6 @@ struct InstId : public IdBase<InstId> {
|
||||
static constexpr llvm::StringLiteral Label = "inst";
|
||||
using ValueType = Inst;
|
||||
|
||||
// An ID with no value.
|
||||
static const InstId None;
|
||||
|
||||
// Represents the result of a name lookup that is temporarily disallowed
|
||||
// because the name is currently being initialized.
|
||||
static const InstId InitTombstone;
|
||||
@@ -52,8 +49,7 @@ struct InstId : public IdBase<InstId> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr InstId InstId::None = InstId(NoneIndex);
|
||||
constexpr InstId InstId::InitTombstone = InstId(NoneIndex - 2);
|
||||
constexpr InstId InstId::InitTombstone = InstId(NoneIndex - 1);
|
||||
|
||||
// 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
|
||||
@@ -113,8 +109,6 @@ struct ConstantId : public IdBase<ConstantId> {
|
||||
|
||||
// An ID for an expression that is not constant.
|
||||
static const ConstantId NotConstant;
|
||||
// An ID with no value.
|
||||
static const ConstantId None;
|
||||
|
||||
// Returns the constant ID corresponding to a concrete constant, which should
|
||||
// either be in the `constants` block in the file or should be known to be
|
||||
@@ -180,36 +174,24 @@ struct ConstantId : public IdBase<ConstantId> {
|
||||
};
|
||||
|
||||
constexpr ConstantId ConstantId::NotConstant = ConstantId(NotConstantIndex);
|
||||
constexpr ConstantId ConstantId::None = ConstantId(NoneIndex);
|
||||
|
||||
// The ID of a EntityName.
|
||||
struct EntityNameId : public IdBase<EntityNameId> {
|
||||
static constexpr llvm::StringLiteral Label = "entity_name";
|
||||
using ValueType = EntityName;
|
||||
|
||||
// An ID with no value.
|
||||
static const EntityNameId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr EntityNameId EntityNameId::None = EntityNameId(NoneIndex);
|
||||
|
||||
// The index of a compile-time binding. This is the de Bruijn level for the
|
||||
// binding -- that is, this is the number of other compile time bindings whose
|
||||
// scope encloses this binding.
|
||||
struct CompileTimeBindIndex : public IndexBase<CompileTimeBindIndex> {
|
||||
static constexpr llvm::StringLiteral Label = "comp_time_bind";
|
||||
|
||||
// An index with no value.
|
||||
static const CompileTimeBindIndex None;
|
||||
|
||||
using IndexBase::IndexBase;
|
||||
};
|
||||
|
||||
constexpr CompileTimeBindIndex CompileTimeBindIndex::None =
|
||||
CompileTimeBindIndex(NoneIndex);
|
||||
|
||||
// The index of a runtime parameter in a function. These are allocated
|
||||
// sequentially, left-to-right, to the function parameters that will have
|
||||
// arguments passed to them at runtime. In a `call` instruction, a runtime
|
||||
@@ -220,9 +202,6 @@ constexpr CompileTimeBindIndex CompileTimeBindIndex::None =
|
||||
struct RuntimeParamIndex : public IndexBase<RuntimeParamIndex> {
|
||||
static constexpr llvm::StringLiteral Label = "runtime_param";
|
||||
|
||||
// An index with no value.
|
||||
static const RuntimeParamIndex None;
|
||||
|
||||
// An placeholder for index whose value is not yet known.
|
||||
static const RuntimeParamIndex Unknown;
|
||||
|
||||
@@ -231,9 +210,6 @@ struct RuntimeParamIndex : public IndexBase<RuntimeParamIndex> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr RuntimeParamIndex RuntimeParamIndex::None =
|
||||
RuntimeParamIndex(NoneIndex);
|
||||
|
||||
constexpr RuntimeParamIndex RuntimeParamIndex::Unknown =
|
||||
RuntimeParamIndex(NoneIndex - 1);
|
||||
|
||||
@@ -242,14 +218,9 @@ struct FunctionId : public IdBase<FunctionId> {
|
||||
static constexpr llvm::StringLiteral Label = "function";
|
||||
using ValueType = Function;
|
||||
|
||||
// An ID with no value.
|
||||
static const FunctionId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr FunctionId FunctionId::None = FunctionId(NoneIndex);
|
||||
|
||||
// The ID of an IR within the set of all IRs being evaluated in the current
|
||||
// check execution.
|
||||
struct CheckIRId : public IdBase<CheckIRId> {
|
||||
@@ -262,109 +233,66 @@ struct ClassId : public IdBase<ClassId> {
|
||||
static constexpr llvm::StringLiteral Label = "class";
|
||||
using ValueType = Class;
|
||||
|
||||
// An ID with no value.
|
||||
static const ClassId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr ClassId ClassId::None = ClassId(NoneIndex);
|
||||
|
||||
// The ID of an interface.
|
||||
struct InterfaceId : public IdBase<InterfaceId> {
|
||||
static constexpr llvm::StringLiteral Label = "interface";
|
||||
using ValueType = Interface;
|
||||
|
||||
// An ID with no value.
|
||||
static const InterfaceId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr InterfaceId InterfaceId::None = InterfaceId(NoneIndex);
|
||||
|
||||
// The ID of an associated constant.
|
||||
struct AssociatedConstantId : public IdBase<AssociatedConstantId> {
|
||||
static constexpr llvm::StringLiteral Label = "assoc_const";
|
||||
using ValueType = AssociatedConstant;
|
||||
|
||||
// An ID with no value.
|
||||
static const AssociatedConstantId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr AssociatedConstantId AssociatedConstantId::None =
|
||||
AssociatedConstantId(NoneIndex);
|
||||
|
||||
// The ID of an facet type value.
|
||||
struct FacetTypeId : public IdBase<FacetTypeId> {
|
||||
static constexpr llvm::StringLiteral Label = "facet_type";
|
||||
using ValueType = FacetTypeInfo;
|
||||
|
||||
// An ID with no value.
|
||||
static const FacetTypeId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr FacetTypeId FacetTypeId::None = FacetTypeId(NoneIndex);
|
||||
|
||||
// The ID of an resolved facet type value.
|
||||
struct CompleteFacetTypeId : public IdBase<CompleteFacetTypeId> {
|
||||
static constexpr llvm::StringLiteral Label = "complete_facet_type";
|
||||
using ValueType = CompleteFacetType;
|
||||
|
||||
// An ID with no value.
|
||||
static const CompleteFacetTypeId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr CompleteFacetTypeId CompleteFacetTypeId::None =
|
||||
CompleteFacetTypeId(NoneIndex);
|
||||
|
||||
// The ID of an impl.
|
||||
struct ImplId : public IdBase<ImplId> {
|
||||
static constexpr llvm::StringLiteral Label = "impl";
|
||||
using ValueType = Impl;
|
||||
|
||||
// An ID with no value.
|
||||
static const ImplId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr ImplId ImplId::None = ImplId(NoneIndex);
|
||||
|
||||
// The ID of a generic.
|
||||
struct GenericId : public IdBase<GenericId> {
|
||||
static constexpr llvm::StringLiteral Label = "generic";
|
||||
using ValueType = Generic;
|
||||
|
||||
// An ID with no value.
|
||||
static const GenericId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr GenericId GenericId::None = GenericId(NoneIndex);
|
||||
|
||||
// The ID of a specific, which is the result of specifying the generic arguments
|
||||
// for a generic.
|
||||
struct SpecificId : public IdBase<SpecificId> {
|
||||
static constexpr llvm::StringLiteral Label = "specific";
|
||||
using ValueType = Specific;
|
||||
|
||||
// An ID with no value. This is typically used to represent a non-generic
|
||||
// entity.
|
||||
static const SpecificId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr SpecificId SpecificId::None = SpecificId(NoneIndex);
|
||||
|
||||
// The index of an instruction that depends on generic parameters within a
|
||||
// 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
|
||||
@@ -419,22 +347,14 @@ struct ImportCppId : public IdBase<ImportCppId> {
|
||||
static constexpr llvm::StringLiteral Label = "import_cpp";
|
||||
using ValueType = ImportCpp;
|
||||
|
||||
// An ID with no value.
|
||||
static const ImportCppId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr ImportCppId ImportCppId::None = ImportCppId(NoneIndex);
|
||||
|
||||
// The ID of an IR within the set of imported IRs, both direct and indirect.
|
||||
struct ImportIRId : public IdBase<ImportIRId> {
|
||||
static constexpr llvm::StringLiteral Label = "ir";
|
||||
using ValueType = ImportIR;
|
||||
|
||||
// An ID with no value.
|
||||
static const ImportIRId None;
|
||||
|
||||
// The implicit `api` import, for an `impl` file. A null entry is added if
|
||||
// there is none, as in an `api`, in which case this ID should not show up in
|
||||
// instructions.
|
||||
@@ -443,7 +363,6 @@ struct ImportIRId : public IdBase<ImportIRId> {
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr ImportIRId ImportIRId::None = ImportIRId(NoneIndex);
|
||||
constexpr ImportIRId ImportIRId::ApiForImpl = ImportIRId(0);
|
||||
|
||||
// A boolean value.
|
||||
@@ -536,9 +455,6 @@ struct NameId : public IdBase<NameId> {
|
||||
// names().GetFormatted() is used for diagnostics.
|
||||
using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
|
||||
// An ID with no value.
|
||||
static const NameId None;
|
||||
|
||||
// An enum of special names.
|
||||
enum class SpecialNameId : uint8_t {
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_ENUM(Name) Name,
|
||||
@@ -582,8 +498,6 @@ struct NameId : public IdBase<NameId> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr NameId NameId::None = NameId(NoneIndex);
|
||||
|
||||
// Define the special `static const NameId` values.
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_DEF(Name) \
|
||||
constexpr NameId NameId::Name = \
|
||||
@@ -602,15 +516,12 @@ struct NameScopeId : public IdBase<NameScopeId> {
|
||||
static constexpr llvm::StringLiteral Label = "name_scope";
|
||||
using ValueType = NameScope;
|
||||
|
||||
// An ID with no value.
|
||||
static const NameScopeId None;
|
||||
// The package (or file) name scope, guaranteed to be the first added.
|
||||
static const NameScopeId Package;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr NameScopeId NameScopeId::None = NameScopeId(NoneIndex);
|
||||
constexpr NameScopeId NameScopeId::Package = NameScopeId(0);
|
||||
|
||||
// The ID of an instruction block.
|
||||
@@ -637,9 +548,6 @@ struct InstBlockId : public IdBase<InstBlockId> {
|
||||
// be inserted into it.
|
||||
static const InstBlockId GlobalInit;
|
||||
|
||||
// An ID with no value.
|
||||
static const InstBlockId None;
|
||||
|
||||
// An ID for unreachable code.
|
||||
static const InstBlockId Unreachable;
|
||||
|
||||
@@ -651,7 +559,6 @@ constexpr InstBlockId InstBlockId::Empty = InstBlockId(0);
|
||||
constexpr InstBlockId InstBlockId::Exports = InstBlockId(1);
|
||||
constexpr InstBlockId InstBlockId::ImportRefs = InstBlockId(2);
|
||||
constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(3);
|
||||
constexpr InstBlockId InstBlockId::None = InstBlockId(NoneIndex);
|
||||
constexpr InstBlockId InstBlockId::Unreachable = InstBlockId(NoneIndex - 1);
|
||||
|
||||
// An ID of an instruction block that is referenced absolutely by an
|
||||
@@ -704,14 +611,9 @@ struct ExprRegionId : public IdBase<ExprRegionId> {
|
||||
static constexpr llvm::StringLiteral Label = "region";
|
||||
using ValueType = ExprRegion;
|
||||
|
||||
// An ID with no value.
|
||||
static const ExprRegionId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr ExprRegionId ExprRegionId::None = ExprRegionId(NoneIndex);
|
||||
|
||||
// The ID of a struct type field block.
|
||||
struct StructTypeFieldsId : public IdBase<StructTypeFieldsId> {
|
||||
static constexpr llvm::StringLiteral Label = "struct_type_fields";
|
||||
@@ -719,9 +621,6 @@ struct StructTypeFieldsId : public IdBase<StructTypeFieldsId> {
|
||||
using ElementType = StructTypeField;
|
||||
using ValueType = llvm::MutableArrayRef<StructTypeField>;
|
||||
|
||||
// An ID with no value.
|
||||
static const StructTypeFieldsId None;
|
||||
|
||||
// The canonical empty block, reused to avoid allocating empty vectors. Always
|
||||
// the 0-index block.
|
||||
static const StructTypeFieldsId Empty;
|
||||
@@ -729,8 +628,6 @@ struct StructTypeFieldsId : public IdBase<StructTypeFieldsId> {
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr StructTypeFieldsId StructTypeFieldsId::None =
|
||||
StructTypeFieldsId(NoneIndex);
|
||||
constexpr StructTypeFieldsId StructTypeFieldsId::Empty = StructTypeFieldsId(0);
|
||||
|
||||
// The ID of a type.
|
||||
@@ -742,9 +639,6 @@ struct TypeId : public IdBase<TypeId> {
|
||||
// `InstIdAsType` or `TypeOfInstId` as the diagnostic argument type.
|
||||
using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
|
||||
// An ID with no value.
|
||||
static const TypeId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
|
||||
// Returns the ID of the type corresponding to the constant `const_id`, which
|
||||
@@ -765,8 +659,6 @@ struct TypeId : public IdBase<TypeId> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr TypeId TypeId::None = TypeId(NoneIndex);
|
||||
|
||||
// The ID of a type block.
|
||||
struct TypeBlockId : public IdBase<TypeBlockId> {
|
||||
static constexpr llvm::StringLiteral Label = "type_block";
|
||||
@@ -774,9 +666,6 @@ struct TypeBlockId : public IdBase<TypeBlockId> {
|
||||
using ElementType = TypeId;
|
||||
using ValueType = llvm::MutableArrayRef<ElementType>;
|
||||
|
||||
// An ID with no value.
|
||||
static const TypeBlockId None;
|
||||
|
||||
// The canonical empty block, reused to avoid allocating empty vectors. Always
|
||||
// the 0-index block.
|
||||
static const TypeBlockId Empty;
|
||||
@@ -784,27 +673,19 @@ struct TypeBlockId : public IdBase<TypeBlockId> {
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr TypeBlockId TypeBlockId::None = TypeBlockId(NoneIndex);
|
||||
constexpr TypeBlockId TypeBlockId::Empty = TypeBlockId(0);
|
||||
|
||||
// An index for element access, for structs, tuples, and classes.
|
||||
struct ElementIndex : public IndexBase<ElementIndex> {
|
||||
static constexpr llvm::StringLiteral Label = "element";
|
||||
using IndexBase::IndexBase;
|
||||
|
||||
// An ID with no value.
|
||||
static const ElementIndex None;
|
||||
};
|
||||
|
||||
constexpr ElementIndex ElementIndex::None = ElementIndex(NoneIndex);
|
||||
|
||||
// The ID of a library name. This is either a string literal or `default`.
|
||||
struct LibraryNameId : public IdBase<LibraryNameId> {
|
||||
static constexpr llvm::StringLiteral Label = "library_name";
|
||||
using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
|
||||
// An ID with no value.
|
||||
static const LibraryNameId None;
|
||||
// The name of `default`.
|
||||
static const LibraryNameId Default;
|
||||
// Track cases where the library name was set, but has been diagnosed and
|
||||
@@ -825,7 +706,6 @@ struct LibraryNameId : public IdBase<LibraryNameId> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr LibraryNameId LibraryNameId::None = LibraryNameId(NoneIndex);
|
||||
constexpr LibraryNameId LibraryNameId::Default = LibraryNameId(NoneIndex - 1);
|
||||
constexpr LibraryNameId LibraryNameId::Error = LibraryNameId(NoneIndex - 2);
|
||||
|
||||
@@ -834,14 +714,9 @@ struct ImportIRInstId : public IdBase<ImportIRInstId> {
|
||||
static constexpr llvm::StringLiteral Label = "import_ir_inst";
|
||||
using ValueType = ImportIRInst;
|
||||
|
||||
// An ID with no value.
|
||||
static const ImportIRInstId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
constexpr ImportIRInstId ImportIRInstId::None = ImportIRInstId(NoneIndex);
|
||||
|
||||
// A SemIR location used as the location of instructions.
|
||||
//
|
||||
// Contents:
|
||||
@@ -855,9 +730,6 @@ struct LocId : public IdBase<LocId> {
|
||||
// operations performed implicitly.
|
||||
static const int32_t ImplicitBit = 1 << 30;
|
||||
|
||||
// An ID with no value.
|
||||
static const LocId None;
|
||||
|
||||
using IdBase::IdBase;
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
@@ -909,8 +781,6 @@ struct LocId : public IdBase<LocId> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr LocId LocId::None = LocId(Parse::NodeId::None);
|
||||
|
||||
// Polymorphic id for fields in `Any[...]` typed instruction category. Used for
|
||||
// fields where the specific instruction structs have different field types in
|
||||
// that position or do not have a field in that position at all. Allows
|
||||
|
||||
Reference in New Issue
Block a user