Quellcode durchsuchen

Add Inst::IsOneOf to check if an inst is one of a few kinds (#6523)

Adds Inst::IsOneOf which takes a variadic generic parameter pack of
kinds to check against. Also add forwarding functions to TypeStore and
InstStore. Convert uses of the regex `Is<.*\|\|` to IsOneOf.

This is based on #6522
Dana Jansens vor 3 Monaten
Ursprung
Commit
30562826b8

+ 4 - 4
toolchain/check/convert.cpp

@@ -998,8 +998,8 @@ static auto PerformBuiltinConversion(
     if (auto foundation_type_id =
     if (auto foundation_type_id =
             context.types().GetTransitiveAdaptedType(value_type_id);
             context.types().GetTransitiveAdaptedType(value_type_id);
         foundation_type_id != value_type_id &&
         foundation_type_id != value_type_id &&
-        (context.types().Is<SemIR::TupleType>(foundation_type_id) ||
-         context.types().Is<SemIR::StructType>(foundation_type_id))) {
+        context.types().IsOneOf<SemIR::StructType, SemIR::TupleType>(
+            foundation_type_id)) {
       auto foundation_value_id = AddInst<SemIR::AsCompatible>(
       auto foundation_value_id = AddInst<SemIR::AsCompatible>(
           context, loc_id,
           context, loc_id,
           {.type_id = foundation_type_id, .source_id = value_id});
           {.type_id = foundation_type_id, .source_id = value_id});
@@ -1264,8 +1264,8 @@ static auto PerformBuiltinConversion(
   // other facet values, as long as they satisfy the required interfaces of the
   // other facet values, as long as they satisfy the required interfaces of the
   // target `FacetType`.
   // target `FacetType`.
   if (sem_ir.types().Is<SemIR::FacetType>(target.type_id) &&
   if (sem_ir.types().Is<SemIR::FacetType>(target.type_id) &&
-      (sem_ir.types().Is<SemIR::TypeType>(value_type_id) ||
-       sem_ir.types().Is<SemIR::FacetType>(value_type_id))) {
+      sem_ir.types().IsOneOf<SemIR::TypeType, SemIR::FacetType>(
+          value_type_id)) {
     // TODO: Runtime facet values should be allowed to convert based on their
     // TODO: Runtime facet values should be allowed to convert based on their
     // FacetTypes, but we assume constant values for impl lookup at the moment.
     // FacetTypes, but we assume constant values for impl lookup at the moment.
     if (!context.constant_values().Get(value_id).is_constant()) {
     if (!context.constant_values().Get(value_id).is_constant()) {

+ 1 - 2
toolchain/check/generic.cpp

@@ -149,8 +149,7 @@ class RebuildGenericConstantInEvalBlockCallbacks : public SubstInstCallbacks {
   auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {
   auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {
     auto inst = context().insts().Get(orig_inst_id);
     auto inst = context().insts().Get(orig_inst_id);
     CARBON_CHECK(
     CARBON_CHECK(
-        inst.Is<SemIR::SymbolicBinding>() ||
-            inst.Is<SemIR::SymbolicBindingPattern>(),
+        (inst.IsOneOf<SemIR::SymbolicBinding, SemIR::SymbolicBindingPattern>()),
         "Instruction {0} has symbolic constant value but no symbolic operands",
         "Instruction {0} has symbolic constant value but no symbolic operands",
         inst);
         inst);
 
 

+ 2 - 2
toolchain/check/impl_lookup.cpp

@@ -578,8 +578,8 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
         context.insts()
         context.insts()
             .Get(context.constant_values().GetInstId(query_self_const_id))
             .Get(context.constant_values().GetInstId(query_self_const_id))
             .type_id();
             .type_id();
-    CARBON_CHECK(context.types().Is<SemIR::TypeType>(query_self_type_id) ||
-                 context.types().Is<SemIR::FacetType>(query_self_type_id));
+    CARBON_CHECK((context.types().IsOneOf<SemIR::TypeType, SemIR::FacetType>(
+        query_self_type_id)));
     // The query facet type value is indeed a facet type.
     // The query facet type value is indeed a facet type.
     CARBON_CHECK(context.insts().Is<SemIR::FacetType>(
     CARBON_CHECK(context.insts().Is<SemIR::FacetType>(
         context.constant_values().GetInstId(query_facet_type_const_id)));
         context.constant_values().GetInstId(query_facet_type_const_id)));

+ 1 - 2
toolchain/check/import_ref.cpp

@@ -865,8 +865,7 @@ static auto GetLocalConstantId(ImportRefResolver& resolver,
   auto import_decl_inst_id = resolver.import_generics().Get(generic_id).decl_id;
   auto import_decl_inst_id = resolver.import_generics().Get(generic_id).decl_id;
   auto import_decl_inst =
   auto import_decl_inst =
       resolver.import_insts().GetWithAttachedType(import_decl_inst_id);
       resolver.import_insts().GetWithAttachedType(import_decl_inst_id);
-  if (import_decl_inst.Is<SemIR::ImplDecl>() ||
-      import_decl_inst.Is<SemIR::RequireImplsDecl>()) {
+  if (import_decl_inst.IsOneOf<SemIR::ImplDecl, SemIR::RequireImplsDecl>()) {
     // For these decl types, the imported entity can be found via the
     // For these decl types, the imported entity can be found via the
     // declaration's operands.
     // declaration's operands.
     return GetLocalConstantId(resolver, import_decl_inst_id);
     return GetLocalConstantId(resolver, import_decl_inst_id);

+ 2 - 3
toolchain/lower/handle_aggregates.cpp

@@ -45,9 +45,8 @@ static auto GetElementIndex(FunctionContext::TypeInFile type,
 
 
   // For now, struct and tuple types map directly into LLVM struct types with
   // For now, struct and tuple types map directly into LLVM struct types with
   // identical field numbering.
   // identical field numbering.
-  CARBON_CHECK(
-      type_inst.Is<SemIR::StructType>() || type_inst.Is<SemIR::TupleType>(),
-      "Indexing unexpected aggregate type {0}", type_inst);
+  CARBON_CHECK((type_inst.IsOneOf<SemIR::StructType, SemIR::TupleType>()),
+               "Indexing unexpected aggregate type {0}", type_inst);
   return idx.index;
   return idx.index;
 }
 }
 
 

+ 1 - 2
toolchain/sem_ir/builtin_function_kind.cpp

@@ -758,8 +758,7 @@ static auto IsLiteralType(const File& sem_ir, TypeId type_id) -> bool {
   // Unwrap adapters.
   // Unwrap adapters.
   type_id = sem_ir.types().GetTransitiveAdaptedType(type_id);
   type_id = sem_ir.types().GetTransitiveAdaptedType(type_id);
   auto type_inst_id = sem_ir.types().GetAsInst(type_id);
   auto type_inst_id = sem_ir.types().GetAsInst(type_id);
-  return type_inst_id.Is<IntLiteralType>() ||
-         type_inst_id.Is<FloatLiteralType>();
+  return type_inst_id.IsOneOf<IntLiteralType, FloatLiteralType>();
 }
 }
 
 
 // Determines whether a builtin call involves an integer or floating-point
 // Determines whether a builtin call involves an integer or floating-point

+ 13 - 0
toolchain/sem_ir/inst.h

@@ -259,6 +259,13 @@ class Inst : public Printable<Inst> {
     return Internal::InstLikeTypeInfo<TypedInst>::IsKind(kind());
     return Internal::InstLikeTypeInfo<TypedInst>::IsKind(kind());
   }
   }
 
 
+  // Returns whether this instruction has one of the specified types.
+  template <typename... TypedInsts>
+    requires(... && Internal::InstLikeType<TypedInsts>)
+  auto IsOneOf() const -> bool {
+    return (... || Internal::InstLikeTypeInfo<TypedInsts>::IsKind(kind()));
+  }
+
   // Casts this instruction to the given typed instruction, which must match the
   // Casts this instruction to the given typed instruction, which must match the
   // instruction's kind, and returns the typed instruction.
   // instruction's kind, and returns the typed instruction.
   template <typename TypedInst>
   template <typename TypedInst>
@@ -504,6 +511,12 @@ class InstStore {
     return Get(inst_id).Is<InstT>();
     return Get(inst_id).Is<InstT>();
   }
   }
 
 
+  // Returns whether the requested instruction is one of the specified types.
+  template <typename... InstTs>
+  auto IsOneOf(InstId inst_id) const -> bool {
+    return Get(inst_id).Is<InstTs...>();
+  }
+
   // Returns the requested instruction, which is known to have the specified
   // Returns the requested instruction, which is known to have the specified
   // type.
   // type.
   template <typename InstT>
   template <typename InstT>

+ 7 - 0
toolchain/sem_ir/type.h

@@ -112,6 +112,13 @@ class TypeStore : public Yaml::Printable<TypeStore> {
     return GetAsInst(type_id).Is<InstT>();
     return GetAsInst(type_id).Is<InstT>();
   }
   }
 
 
+  // Returns whether one of the specified kinds of instruction was used to
+  // define the type.
+  template <typename... InstTs>
+  auto IsOneOf(TypeId type_id) const -> bool {
+    return GetAsInst(type_id).IsOneOf<InstTs...>();
+  }
+
   // Returns the instruction used to define the specified type, which is known
   // Returns the instruction used to define the specified type, which is known
   // to be a particular kind of instruction.
   // to be a particular kind of instruction.
   template <typename InstT>
   template <typename InstT>