Add an EnumMaskBase type (#6053)

This is a bit of an experiment to see if there's a reasonable way to
write a shared enum type, rather than writing per-case wrappers for
things like `HasTypeQualifiers` or the printing. I think it's a bit
borderline complexity right now, but I'm not sure I can reduce it much
further.

This changes from things like `Internal::EnumClassName##RawEnum` to
`Internal::EnumClassName##Data::RawEnum` so that the enum entries can
have back references to bit shifts without needing to know the
containing type name. Because I'm trying to reduce duplication between
mask and non-mask enums, I did this to non-mask enums too.

This was motivated by #6035 adding another enum mask (which will grow
more entries, and is intended to switch if this is accepted), but I'm
not using that PR as a base here because I didn't want the merge
dependency.
This commit is contained in:
Jon Ross-Perkins
2025-09-12 18:04:10 +00:00
committed by GitHub
parent 508a88e2a9
commit 6cc5d7ed2a
17 changed files with 368 additions and 229 deletions
+7 -4
View File
@@ -23,6 +23,9 @@
namespace Carbon::Check {
CARBON_DEFINE_ENUM_MASK_NAMES(DependentInstKind) = {
CARBON_DEPENDENT_INST_KIND(CARBON_ENUM_MASK_NAME_STRING)};
static auto MakeSelfSpecificId(Context& context, SemIR::GenericId generic_id)
-> SemIR::SpecificId;
@@ -302,14 +305,14 @@ auto AttachDependentInstToCurrentGeneric(Context& context,
if (context.generic_region_stack().Empty()) {
// This should only happen for `*Decl` instructions, never for template
// actions.
CARBON_CHECK((dep_kind & DependentInst::Template) == DependentInst::None);
CARBON_CHECK(!dep_kind.HasAnyOf(DependentInstKind::Template));
return;
}
context.generic_region_stack().AddDependentInst(dependent_inst.inst_id);
// If the type is symbolic, replace it with a type specific to this generic.
if ((dep_kind & DependentInst::SymbolicType) != DependentInst::None) {
if (dep_kind.HasAnyOf(DependentInstKind::SymbolicType)) {
auto inst = context.insts().Get(inst_id);
auto type_id = AddGenericTypeToEvalBlock(context, SemIR::LocId(inst_id),
inst.type_id());
@@ -327,7 +330,7 @@ auto AttachDependentInstToCurrentGeneric(Context& context,
// 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 & DependentInst::SymbolicConstant) != DependentInst::None) {
if (dep_kind.HasAnyOf(DependentInstKind::SymbolicConstant)) {
// Update the constant value to refer to this generic.
context.constant_values().Set(
inst_id, AddGenericConstantToEvalBlock(context, inst_id));
@@ -335,7 +338,7 @@ auto AttachDependentInstToCurrentGeneric(Context& context,
// If the instruction is a template action, add it directly to this position
// in the eval block.
if ((dep_kind & DependentInst::Template) != DependentInst::None) {
if (dep_kind.HasAnyOf(DependentInstKind::Template)) {
AddTemplateActionToEvalBlock(context, inst_id);
}
}