Просмотр исходного кода

Switch check code to use CARBON_KIND_SWITCH (#3873)

This is intended to have no user-visible effect, only aiming for a style
change/simplification.
Jon Ross-Perkins 2 лет назад
Родитель
Сommit
4ed0d95777

+ 1 - 0
toolchain/check/BUILD

@@ -125,6 +125,7 @@ cc_library(
         "//common:ostream",
         "//common:variant_helpers",
         "//common:vlog",
+        "//toolchain/base:kind_switch",
         "//toolchain/base:pretty_stack_trace_function",
         "//toolchain/base:value_store",
         "//toolchain/diagnostics:diagnostic_emitter",

+ 36 - 38
toolchain/check/context.cpp

@@ -10,6 +10,7 @@
 #include "common/check.h"
 #include "common/vlog.h"
 #include "llvm/ADT/Sequence.h"
+#include "toolchain/base/kind_switch.h"
 #include "toolchain/check/decl_name_stack.h"
 #include "toolchain/check/eval.h"
 #include "toolchain/check/import_ref.h"
@@ -733,34 +734,32 @@ class TypeCompleter {
   // Adds any types nested within `type_inst` that need to be complete for
   // `type_inst` to be complete to our work list.
   auto AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool {
-    switch (type_inst.kind()) {
-      case SemIR::ArrayType::Kind:
-        Push(type_inst.As<SemIR::ArrayType>().element_type_id);
+    CARBON_KIND_SWITCH(type_inst) {
+      case CARBON_KIND(SemIR::ArrayType inst): {
+        Push(inst.element_type_id);
         break;
-
-      case SemIR::StructType::Kind:
-        for (auto field_id : context_.inst_blocks().Get(
-                 type_inst.As<SemIR::StructType>().fields_id)) {
+      }
+      case CARBON_KIND(SemIR::StructType inst): {
+        for (auto field_id : context_.inst_blocks().Get(inst.fields_id)) {
           Push(context_.insts()
                    .GetAs<SemIR::StructTypeField>(field_id)
                    .field_type_id);
         }
         break;
-
-      case SemIR::TupleType::Kind:
-        for (auto element_type_id : context_.type_blocks().Get(
-                 type_inst.As<SemIR::TupleType>().elements_id)) {
+      }
+      case CARBON_KIND(SemIR::TupleType inst): {
+        for (auto element_type_id :
+             context_.type_blocks().Get(inst.elements_id)) {
           Push(element_type_id);
         }
         break;
-
-      case SemIR::ClassType::Kind: {
-        auto class_type = type_inst.As<SemIR::ClassType>();
-        auto& class_info = context_.classes().Get(class_type.class_id);
+      }
+      case CARBON_KIND(SemIR::ClassType inst): {
+        auto& class_info = context_.classes().Get(inst.class_id);
         if (!class_info.is_defined()) {
           if (diagnoser_) {
             auto builder = (*diagnoser_)();
-            context_.NoteIncompleteClass(class_type.class_id, builder);
+            context_.NoteIncompleteClass(inst.class_id, builder);
             builder.Emit();
           }
           return false;
@@ -768,11 +767,10 @@ class TypeCompleter {
         Push(class_info.object_repr_id);
         break;
       }
-
-      case SemIR::ConstType::Kind:
-        Push(type_inst.As<SemIR::ConstType>().inner_id);
+      case CARBON_KIND(SemIR::ConstType inst): {
+        Push(inst.inner_id);
         break;
-
+      }
       default:
         break;
     }
@@ -951,7 +949,7 @@ class TypeCompleter {
   // types, as found by AddNestedIncompleteTypes, are known to be complete.
   auto BuildValueRepr(SemIR::TypeId type_id, SemIR::Inst inst) const
       -> SemIR::ValueRepr {
-    switch (inst.kind()) {
+    CARBON_KIND_SWITCH(inst) {
       case SemIR::AddrOf::Kind:
       case SemIR::AddrPattern::Kind:
       case SemIR::ArrayIndex::Kind:
@@ -1023,29 +1021,28 @@ class TypeCompleter {
         return BuildAnyImportRefValueRepr(type_id,
                                           inst.As<SemIR::AnyImportRef>());
 
-      case SemIR::StructType::Kind:
-        return BuildStructTypeValueRepr(type_id, inst.As<SemIR::StructType>());
-
-      case SemIR::TupleType::Kind:
-        return BuildTupleTypeValueRepr(type_id, inst.As<SemIR::TupleType>());
-
-      case SemIR::ClassType::Kind:
+      case CARBON_KIND(SemIR::StructType struct_type): {
+        return BuildStructTypeValueRepr(type_id, struct_type);
+      }
+      case CARBON_KIND(SemIR::TupleType tuple_type): {
+        return BuildTupleTypeValueRepr(type_id, tuple_type);
+      }
+      case CARBON_KIND(SemIR::ClassType class_type): {
         // The value representation for a class is a pointer to the object
         // representation.
         // TODO: Support customized value representations for classes.
         // TODO: Pick a better value representation when possible.
         return MakePointerValueRepr(
-            context_.classes()
-                .Get(inst.As<SemIR::ClassType>().class_id)
-                .object_repr_id,
+            context_.classes().Get(class_type.class_id).object_repr_id,
             SemIR::ValueRepr::ObjectAggregate);
-
-      case SemIR::InterfaceType::Kind:
+      }
+      case SemIR::InterfaceType::Kind: {
         // TODO: Should we model the value representation as a witness?
         return MakeEmptyValueRepr();
-
-      case SemIR::Builtin::Kind:
-        return BuildBuiltinValueRepr(type_id, inst.As<SemIR::Builtin>());
+      }
+      case CARBON_KIND(SemIR::Builtin builtin): {
+        return BuildBuiltinValueRepr(type_id, builtin);
+      }
 
       case SemIR::AssociatedEntityType::Kind:
       case SemIR::BindSymbolicName::Kind:
@@ -1054,10 +1051,11 @@ class TypeCompleter {
       case SemIR::UnboundElementType::Kind:
         return MakeCopyValueRepr(type_id);
 
-      case SemIR::ConstType::Kind:
+      case CARBON_KIND(SemIR::ConstType const_type): {
         // The value representation of `const T` is the same as that of `T`.
         // Objects are not modifiable through their value representations.
-        return GetNestedValueRepr(inst.As<SemIR::ConstType>().inner_id);
+        return GetNestedValueRepr(const_type.inner_id);
+      }
     }
   }
 

+ 25 - 25
toolchain/check/convert.cpp

@@ -9,6 +9,7 @@
 
 #include "common/check.h"
 #include "llvm/ADT/STLExtras.h"
+#include "toolchain/base/kind_switch.h"
 #include "toolchain/check/context.h"
 #include "toolchain/sem_ir/copy_on_write_block.h"
 #include "toolchain/sem_ir/file.h"
@@ -23,32 +24,28 @@ static auto FindReturnSlotForInitializer(SemIR::File& sem_ir,
                                          SemIR::InstId init_id)
     -> SemIR::InstId {
   while (true) {
-    SemIR::Inst init = sem_ir.insts().Get(init_id);
-    switch (init.kind()) {
-      default:
-        CARBON_FATAL() << "Initialization from unexpected inst " << init;
-
-      case SemIR::Converted::Kind:
-        init_id = init.As<SemIR::Converted>().result_id;
+    SemIR::Inst init_untyped = sem_ir.insts().Get(init_id);
+    CARBON_KIND_SWITCH(init_untyped) {
+      case CARBON_KIND(SemIR::Converted init): {
+        init_id = init.result_id;
         continue;
-
-      case SemIR::ArrayInit::Kind:
-        return init.As<SemIR::ArrayInit>().dest_id;
-
-      case SemIR::ClassInit::Kind:
-        return init.As<SemIR::ClassInit>().dest_id;
-
-      case SemIR::StructInit::Kind:
-        return init.As<SemIR::StructInit>().dest_id;
-
-      case SemIR::TupleInit::Kind:
-        return init.As<SemIR::TupleInit>().dest_id;
-
-      case SemIR::InitializeFrom::Kind:
-        return init.As<SemIR::InitializeFrom>().dest_id;
-
-      case SemIR::Call::Kind: {
-        auto call = init.As<SemIR::Call>();
+      }
+      case CARBON_KIND(SemIR::ArrayInit init): {
+        return init.dest_id;
+      }
+      case CARBON_KIND(SemIR::ClassInit init): {
+        return init.dest_id;
+      }
+      case CARBON_KIND(SemIR::StructInit init): {
+        return init.dest_id;
+      }
+      case CARBON_KIND(SemIR::TupleInit init): {
+        return init.dest_id;
+      }
+      case CARBON_KIND(SemIR::InitializeFrom init): {
+        return init.dest_id;
+      }
+      case CARBON_KIND(SemIR::Call call): {
         if (!SemIR::GetInitRepr(sem_ir, call.type_id).has_return_slot()) {
           return SemIR::InstId::Invalid;
         }
@@ -58,6 +55,9 @@ static auto FindReturnSlotForInitializer(SemIR::File& sem_ir,
         }
         return sem_ir.inst_blocks().Get(call.args_id).back();
       }
+      default:
+        CARBON_FATAL() << "Initialization from unexpected inst "
+                       << init_untyped;
     }
   }
 }

+ 9 - 10
toolchain/check/decl_name_stack.cpp

@@ -4,6 +4,7 @@
 
 #include "toolchain/check/decl_name_stack.h"
 
+#include "toolchain/base/kind_switch.h"
 #include "toolchain/check/context.h"
 #include "toolchain/sem_ir/ids.h"
 
@@ -209,11 +210,9 @@ auto DeclNameStack::UpdateScopeIfNeeded(NameContext& name_context,
                                         bool is_unqualified) -> void {
   // This will only be reached for resolved instructions. We update the target
   // scope based on the resolved type.
-  auto resolved_inst = context_->insts().Get(name_context.resolved_inst_id);
-  switch (resolved_inst.kind()) {
-    case SemIR::ClassDecl::Kind: {
-      const auto& class_info = context_->classes().Get(
-          resolved_inst.As<SemIR::ClassDecl>().class_id);
+  CARBON_KIND_SWITCH(context_->insts().Get(name_context.resolved_inst_id)) {
+    case CARBON_KIND(SemIR::ClassDecl resolved_inst): {
+      const auto& class_info = context_->classes().Get(resolved_inst.class_id);
       if (class_info.is_defined()) {
         name_context.state = NameContext::State::Resolved;
         name_context.target_scope_id = class_info.scope_id;
@@ -226,9 +225,9 @@ auto DeclNameStack::UpdateScopeIfNeeded(NameContext& name_context,
       }
       break;
     }
-    case SemIR::InterfaceDecl::Kind: {
-      const auto& interface_info = context_->interfaces().Get(
-          resolved_inst.As<SemIR::InterfaceDecl>().interface_id);
+    case CARBON_KIND(SemIR::InterfaceDecl resolved_inst): {
+      const auto& interface_info =
+          context_->interfaces().Get(resolved_inst.interface_id);
       if (interface_info.is_defined()) {
         name_context.state = NameContext::State::Resolved;
         name_context.target_scope_id = interface_info.scope_id;
@@ -241,8 +240,8 @@ auto DeclNameStack::UpdateScopeIfNeeded(NameContext& name_context,
       }
       break;
     }
-    case SemIR::Namespace::Kind: {
-      auto scope_id = resolved_inst.As<SemIR::Namespace>().name_scope_id;
+    case CARBON_KIND(SemIR::Namespace resolved_inst): {
+      auto scope_id = resolved_inst.name_scope_id;
       name_context.state = NameContext::State::Resolved;
       name_context.target_scope_id = scope_id;
       auto& scope = context_->name_scopes().Get(scope_id);

+ 42 - 39
toolchain/check/eval.cpp

@@ -4,6 +4,7 @@
 
 #include "toolchain/check/eval.h"
 
+#include "toolchain/base/kind_switch.h"
 #include "toolchain/check/diagnostic_helpers.h"
 #include "toolchain/diagnostics/diagnostic_emitter.h"
 #include "toolchain/sem_ir/builtin_function_kind.h"
@@ -673,16 +674,16 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     -> SemIR::ConstantId {
   // TODO: Ensure we have test coverage for each of these cases that can result
   // in a constant, once those situations are all reachable.
-  switch (inst.kind()) {
+  CARBON_KIND_SWITCH(inst) {
     // These cases are constants if their operands are.
     case SemIR::AddrOf::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::AddrOf::lvalue_id);
-    case SemIR::ArrayType::Kind:
+    case CARBON_KIND(SemIR::ArrayType array_type): {
       return RebuildAndValidateIfFieldsAreConstant(
           context, inst,
           [&](SemIR::ArrayType result) {
-            auto bound_id = inst.As<SemIR::ArrayType>().bound_id;
+            auto bound_id = array_type.bound_id;
             auto int_bound =
                 context.insts().TryGetAs<SemIR::IntLiteral>(result.bound_id);
             if (!int_bound) {
@@ -713,6 +714,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
             return true;
           },
           &SemIR::ArrayType::bound_id, &SemIR::ArrayType::element_type_id);
+    }
     case SemIR::AssociatedEntityType::Kind:
       return RebuildIfFieldsAreConstant(
           context, inst, &SemIR::AssociatedEntityType::entity_type_id);
@@ -723,14 +725,14 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     case SemIR::InterfaceWitness::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::InterfaceWitness::elements_id);
-    case SemIR::IntType::Kind:
+    case CARBON_KIND(SemIR::IntType int_type): {
       return RebuildAndValidateIfFieldsAreConstant(
           context, inst,
           [&](SemIR::IntType result) {
-            return ValidateIntType(
-                context, inst.As<SemIR::IntType>().bit_width_id, result);
+            return ValidateIntType(context, int_type.bit_width_id, result);
           },
           &SemIR::IntType::bit_width_id);
+    }
     case SemIR::PointerType::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::PointerType::pointee_id);
@@ -773,21 +775,21 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       // Builtins are always template constants.
       return MakeConstantResult(context, inst, Phase::Template);
 
-    case SemIR::ClassDecl::Kind:
+    case CARBON_KIND(SemIR::ClassDecl class_decl): {
       // TODO: Once classes have generic arguments, handle them.
       return MakeConstantResult(
           context,
-          SemIR::ClassType{SemIR::TypeId::TypeType,
-                           inst.As<SemIR::ClassDecl>().class_id},
+          SemIR::ClassType{SemIR::TypeId::TypeType, class_decl.class_id},
           Phase::Template);
-
-    case SemIR::InterfaceDecl::Kind:
+    }
+    case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
       // TODO: Once interfaces have generic arguments, handle them.
       return MakeConstantResult(
           context,
           SemIR::InterfaceType{SemIR::TypeId::TypeType,
-                               inst.As<SemIR::InterfaceDecl>().interface_id},
+                               interface_decl.interface_id},
           Phase::Template);
+    }
 
     case SemIR::ClassType::Kind:
     case SemIR::InterfaceType::Kind:
@@ -825,8 +827,9 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     case SemIR::TupleIndex::Kind:
       return PerformAggregateIndex(context, inst);
 
-    case SemIR::Call::Kind:
-      return PerformCall(context, inst_id, inst.As<SemIR::Call>());
+    case CARBON_KIND(SemIR::Call call): {
+      return PerformCall(context, inst_id, call);
+    }
 
     // TODO: These need special handling.
     case SemIR::BindValue::Kind:
@@ -845,34 +848,34 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       return SemIR::ConstantId::ForSymbolicConstant(inst_id);
 
     // These semantic wrappers don't change the constant value.
-    case SemIR::BindAlias::Kind:
-      return context.constant_values().Get(
-          inst.As<SemIR::BindAlias>().value_id);
-    case SemIR::NameRef::Kind:
-      return context.constant_values().Get(inst.As<SemIR::NameRef>().value_id);
-    case SemIR::Converted::Kind:
-      return context.constant_values().Get(
-          inst.As<SemIR::Converted>().result_id);
-    case SemIR::InitializeFrom::Kind:
-      return context.constant_values().Get(
-          inst.As<SemIR::InitializeFrom>().src_id);
-    case SemIR::SpliceBlock::Kind:
-      return context.constant_values().Get(
-          inst.As<SemIR::SpliceBlock>().result_id);
-    case SemIR::ValueOfInitializer::Kind:
-      return context.constant_values().Get(
-          inst.As<SemIR::ValueOfInitializer>().init_id);
-    case SemIR::FacetTypeAccess::Kind:
+    case CARBON_KIND(SemIR::BindAlias typed_inst): {
+      return context.constant_values().Get(typed_inst.value_id);
+    }
+    case CARBON_KIND(SemIR::NameRef typed_inst): {
+      return context.constant_values().Get(typed_inst.value_id);
+    }
+    case CARBON_KIND(SemIR::Converted typed_inst): {
+      return context.constant_values().Get(typed_inst.result_id);
+    }
+    case CARBON_KIND(SemIR::InitializeFrom typed_inst): {
+      return context.constant_values().Get(typed_inst.src_id);
+    }
+    case CARBON_KIND(SemIR::SpliceBlock typed_inst): {
+      return context.constant_values().Get(typed_inst.result_id);
+    }
+    case CARBON_KIND(SemIR::ValueOfInitializer typed_inst): {
+      return context.constant_values().Get(typed_inst.init_id);
+    }
+    case CARBON_KIND(SemIR::FacetTypeAccess typed_inst): {
       // TODO: Once we start tracking the witness in the facet value, remove it
       // here. For now, we model a facet value as just a type.
-      return context.constant_values().Get(
-          inst.As<SemIR::FacetTypeAccess>().facet_id);
+      return context.constant_values().Get(typed_inst.facet_id);
+    }
 
     // `not true` -> `false`, `not false` -> `true`.
     // All other uses of unary `not` are non-constant.
-    case SemIR::UnaryOperatorNot::Kind: {
-      auto const_id = context.constant_values().Get(
-          inst.As<SemIR::UnaryOperatorNot>().operand_id);
+    case CARBON_KIND(SemIR::UnaryOperatorNot typed_inst): {
+      auto const_id = context.constant_values().Get(typed_inst.operand_id);
       auto phase = GetPhase(const_id);
       if (phase == Phase::Template) {
         auto value =
@@ -887,9 +890,9 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
 
     // `const (const T)` evaluates to `const T`. Otherwise, `const T` evaluates
     // to itself.
-    case SemIR::ConstType::Kind: {
+    case CARBON_KIND(SemIR::ConstType typed_inst): {
       auto inner_id = context.constant_values().Get(
-          context.types().GetInstId(inst.As<SemIR::ConstType>().inner_id));
+          context.types().GetInstId(typed_inst.inner_id));
       if (inner_id.is_constant() &&
           context.insts().Get(inner_id.inst_id()).Is<SemIR::ConstType>()) {
         return inner_id;

+ 5 - 8
toolchain/check/handle_index.cpp

@@ -2,6 +2,7 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
+#include "toolchain/base/kind_switch.h"
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
 #include "toolchain/sem_ir/inst.h"
@@ -40,11 +41,8 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool {
   operand_inst_id = ConvertToValueOrRefExpr(context, operand_inst_id);
   auto operand_inst = context.insts().Get(operand_inst_id);
   auto operand_type_id = operand_inst.type_id();
-  auto operand_type_inst = context.types().GetAsInst(operand_type_id);
-
-  switch (operand_type_inst.kind()) {
-    case SemIR::ArrayType::Kind: {
-      auto array_type = operand_type_inst.As<SemIR::ArrayType>();
+  CARBON_KIND_SWITCH(context.types().GetAsInst(operand_type_id)) {
+    case CARBON_KIND(SemIR::ArrayType array_type): {
       auto index_node_id = context.insts().GetLocId(index_inst_id);
       auto cast_index_id = ConvertToValueOfType(
           context, index_node_id, index_inst_id,
@@ -72,7 +70,7 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool {
       context.node_stack().Push(node_id, elem_id);
       return true;
     }
-    case SemIR::TupleType::Kind: {
+    case CARBON_KIND(SemIR::TupleType tuple_type): {
       SemIR::TypeId element_type_id = SemIR::TypeId::Error;
       auto index_node_id = context.insts().GetLocId(index_inst_id);
       index_inst_id = ConvertToValueOfType(
@@ -90,8 +88,7 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool {
       } else {
         auto index_literal =
             context.insts().GetAs<SemIR::IntLiteral>(index_const_id.inst_id());
-        auto type_block = context.type_blocks().Get(
-            operand_type_inst.As<SemIR::TupleType>().elements_id);
+        auto type_block = context.type_blocks().Get(tuple_type.elements_id);
         if (const auto* index_val =
                 ValidateTupleIndex(context, node_id, operand_inst,
                                    index_literal, type_block.size())) {