From 4ed0d957770f2d4be82a9d7af136cf555559f4c7 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Tue, 9 Apr 2024 16:23:06 +0200 Subject: [PATCH] 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. --- toolchain/check/BUILD | 1 + toolchain/check/context.cpp | 74 +++++++++++++------------- toolchain/check/convert.cpp | 50 +++++++++--------- toolchain/check/decl_name_stack.cpp | 19 ++++--- toolchain/check/eval.cpp | 81 +++++++++++++++-------------- toolchain/check/handle_index.cpp | 13 ++--- 6 files changed, 118 insertions(+), 120 deletions(-) diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index b2fbdbbc0c24..355bf14a6459 100644 --- a/toolchain/check/BUILD +++ b/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", diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 27a6a24a6c55..d5e264c4ce8a 100644 --- a/toolchain/check/context.cpp +++ b/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().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().fields_id)) { + } + case CARBON_KIND(SemIR::StructType inst): { + for (auto field_id : context_.inst_blocks().Get(inst.fields_id)) { Push(context_.insts() .GetAs(field_id) .field_type_id); } break; - - case SemIR::TupleType::Kind: - for (auto element_type_id : context_.type_blocks().Get( - type_inst.As().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(); - 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().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()); - case SemIR::StructType::Kind: - return BuildStructTypeValueRepr(type_id, inst.As()); - - case SemIR::TupleType::Kind: - return BuildTupleTypeValueRepr(type_id, inst.As()); - - 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().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()); + } + 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().inner_id); + return GetNestedValueRepr(const_type.inner_id); + } } } diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 581af82d51c0..b6b2907da1ee 100644 --- a/toolchain/check/convert.cpp +++ b/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().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().dest_id; - - case SemIR::ClassInit::Kind: - return init.As().dest_id; - - case SemIR::StructInit::Kind: - return init.As().dest_id; - - case SemIR::TupleInit::Kind: - return init.As().dest_id; - - case SemIR::InitializeFrom::Kind: - return init.As().dest_id; - - case SemIR::Call::Kind: { - auto call = init.As(); + } + 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; } } } diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index ddc6cd1ab082..628690f7d1b4 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/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().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().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().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); diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 4b439c1cef27..c1d382a86451 100644 --- a/toolchain/check/eval.cpp +++ b/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().bound_id; + auto bound_id = array_type.bound_id; auto int_bound = context.insts().TryGetAs(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().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().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().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()); + 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().value_id); - case SemIR::NameRef::Kind: - return context.constant_values().Get(inst.As().value_id); - case SemIR::Converted::Kind: - return context.constant_values().Get( - inst.As().result_id); - case SemIR::InitializeFrom::Kind: - return context.constant_values().Get( - inst.As().src_id); - case SemIR::SpliceBlock::Kind: - return context.constant_values().Get( - inst.As().result_id); - case SemIR::ValueOfInitializer::Kind: - return context.constant_values().Get( - inst.As().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().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().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().inner_id)); + context.types().GetInstId(typed_inst.inner_id)); if (inner_id.is_constant() && context.insts().Get(inner_id.inst_id()).Is()) { return inner_id; diff --git a/toolchain/check/handle_index.cpp b/toolchain/check/handle_index.cpp index 5b720778bf32..49e13718542f 100644 --- a/toolchain/check/handle_index.cpp +++ b/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(); + 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(index_const_id.inst_id()); - auto type_block = context.type_blocks().Get( - operand_type_inst.As().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())) {