Przeglądaj źródła

Replace `GetTypeInSpecific` with `GetTypeOfInstInSpecific`. (#5232)

Reduce usage of `GetConstantInSpecific` to a single caller in constant
evaluation, with a TODO to remove that.

This gets us closer to being able to fully perform type-checking against
abstract types instead of types anchored within a particular generic.
Richard Smith 1 rok temu
rodzic
commit
c33adfafd3

+ 20 - 10
toolchain/check/eval.cpp

@@ -96,26 +96,36 @@ class EvalContext {
 
     // While resolving a specific, map from previous instructions in the eval
     // block into their evaluated values. These values won't be present on the
-    // specific itself yet, so `GetConstantInSpecific` won't be able to find
-    // them.
-    if (specific_eval_info_) {
-      const auto& symbolic_info =
-          constant_values().GetSymbolicConstant(const_id);
-      if (symbolic_info.index.has_value() &&
-          symbolic_info.generic_id ==
-              specifics().Get(specific_id_).generic_id &&
-          symbolic_info.index.region() == specific_eval_info_->region) {
+    // specific itself yet, so `GetConstantValueInSpecific` won't be able to
+    // find them.
+    const auto& symbolic_info = constant_values().GetSymbolicConstant(const_id);
+    if (specific_eval_info_ && symbolic_info.index.has_value()) {
+      CARBON_CHECK(
+          symbolic_info.generic_id == specifics().Get(specific_id_).generic_id,
+          "Instruction has constant operand in wrong generic");
+      if (symbolic_info.index.region() == specific_eval_info_->region) {
         auto inst_id = specific_eval_info_->values[symbolic_info.index.index()];
         CARBON_CHECK(inst_id.has_value(),
                      "Forward reference in eval block: index {0} referenced "
                      "before evaluation",
                      symbolic_info.index.index());
         return constant_values().Get(inst_id);
+      } else {
+        // TODO: Eliminate this call. This is the only place where we get a
+        // value from a specific without using an InstId. There are three ways
+        // we can get here:
+        // 1) From GetConstantValue(InstId): these can use
+        //    GetConstantValueInSpecific.
+        // 2) From GetConstantValue(TypeId): for these, we could change
+        //    instructions so they store InstIds instead of TypeIds.
+        // 3) From GetConstantFacetTypeInfo: for these, we could store an
+        //    InstId instead of a ConstantId in rewrite_constraints.
+        return GetConstantInSpecific(sem_ir(), specific_id_, const_id);
       }
     }
 
     // Map from a specific constant value to the canonical value.
-    return GetConstantInSpecific(sem_ir(), specific_id_, const_id);
+    return constant_values().Get(symbolic_info.inst_id);
   }
 
   // Gets the constant value of the specified instruction in this context.

+ 1 - 1
toolchain/check/eval_inst.cpp

@@ -243,7 +243,7 @@ auto EvalConstantInst(Context& context, SemIRLoc loc,
 
 auto EvalConstantInst(Context& context, SemIRLoc loc,
                       SemIR::ImplWitnessAccess inst) -> ConstantEvalResult {
-  // This is PerformAggregateAccess followed by GetConstantInSpecific.
+  // This is PerformAggregateAccess followed by GetConstantValueInSpecific.
   if (auto witness =
           context.insts().TryGetAs<SemIR::ImplWitness>(inst.witness_id)) {
     auto elements = context.inst_blocks().Get(witness->elements_id);

+ 4 - 4
toolchain/check/handle_name.cpp

@@ -109,10 +109,10 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id,
                              SemIR::NameId name_id) -> SemIR::InstId {
   auto result = LookupUnqualifiedName(context, node_id, name_id);
   SemIR::InstId inst_id = result.scope_result.target_inst_id();
-  auto value = context.insts().Get(inst_id);
-  auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id,
-                                          value.type_id());
-  CARBON_CHECK(type_id.has_value(), "Missing type for {0}", value);
+  auto type_id = SemIR::GetTypeOfInstInSpecific(context.sem_ir(),
+                                                result.specific_id, inst_id);
+  CARBON_CHECK(type_id.has_value(), "Missing type for {0}",
+               context.insts().Get(inst_id));
 
   // If the named entity has a constant value that depends on its specific,
   // store the specific too.

+ 6 - 8
toolchain/check/interface.cpp

@@ -81,9 +81,8 @@ static auto GetSelfFacet(Context& context,
                          SemIR::InstId self_witness_id) -> SemIR::InstId {
   auto self_binding_id =
       GetSelfBinding(context, interface_specific_id, generic_id);
-  auto self_binding = context.insts().Get(self_binding_id);
-  auto self_facet_type_id = SemIR::GetTypeInSpecific(
-      context.sem_ir(), interface_specific_id, self_binding.type_id());
+  auto self_facet_type_id = SemIR::GetTypeOfInstInSpecific(
+      context.sem_ir(), interface_specific_id, self_binding_id);
   // Create a facet value to be the value of `Self` in the interface.
   // TODO: Pass this in instead of creating it here. The caller sometimes
   // already has a facet value.
@@ -190,15 +189,14 @@ auto GetTypeForSpecificAssociatedEntity(Context& context, SemIRLoc loc,
         GetGenericArgsWithSelfType(context, interface_specific_id, generic_id,
                                    self_type_id, self_witness_id);
     auto const_specific_id = MakeSpecific(context, loc, generic_id, arg_ids);
-    return SemIR::GetTypeInSpecific(context.sem_ir(), const_specific_id,
-                                    context.insts().Get(decl_id).type_id());
+    return SemIR::GetTypeOfInstInSpecific(context.sem_ir(), const_specific_id,
+                                          decl_id);
   } else if (auto fn = context.types().TryGetAs<SemIR::FunctionType>(
                  decl.type_id())) {
     // Form the type of the function within the interface, and attach the `Self`
     // type.
-    auto interface_fn_type_id =
-        SemIR::GetTypeInSpecific(context.sem_ir(), interface_specific_id,
-                                 context.insts().Get(decl_id).type_id());
+    auto interface_fn_type_id = SemIR::GetTypeOfInstInSpecific(
+        context.sem_ir(), interface_specific_id, decl_id);
     auto self_facet_id =
         GetSelfFacet(context, interface_specific_id,
                      context.functions().Get(fn->function_id).generic_id,

+ 5 - 4
toolchain/check/member_access.cpp

@@ -261,10 +261,11 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
   }
 
   // TODO: This duplicates the work that HandleNameAsExpr does. Factor this out.
-  auto inst = context.insts().Get(result.scope_result.target_inst_id());
-  auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id,
-                                          inst.type_id());
-  CARBON_CHECK(type_id.has_value(), "Missing type for member {0}", inst);
+  auto type_id =
+      SemIR::GetTypeOfInstInSpecific(context.sem_ir(), result.specific_id,
+                                     result.scope_result.target_inst_id());
+  CARBON_CHECK(type_id.has_value(), "Missing type for member {0}",
+               context.insts().Get(result.scope_result.target_inst_id()));
 
   // If the named entity has a constant value that depends on its specific,
   // store the specific too.

+ 24 - 15
toolchain/check/merge.cpp

@@ -203,6 +203,9 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
                              SemIR::InstId prev_param_pattern_id,
                              SemIR::SpecificId prev_specific_id, bool diagnose,
                              bool check_self) -> bool {
+  auto orig_new_param_pattern_id = new_param_pattern_id;
+  auto orig_prev_param_pattern_id = prev_param_pattern_id;
+
   // TODO: Consider differentiating between type and name mistakes. For now,
   // taking the simpler approach because I also think we may want to refactor
   // params.
@@ -218,9 +221,10 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
                       "redeclaration differs at {0:implicit |}parameter {1}",
                       Diagnostics::BoolAsSelect, int32_t);
     context.emitter()
-        .Build(new_param_pattern_id, RedeclParamDiffers, is_implicit_param,
+        .Build(orig_new_param_pattern_id, RedeclParamDiffers, is_implicit_param,
                param_index + 1)
-        .Note(prev_param_pattern_id, RedeclParamPrevious, is_implicit_param)
+        .Note(orig_prev_param_pattern_id, RedeclParamPrevious,
+              is_implicit_param)
         .Emit();
   };
 
@@ -232,10 +236,11 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
   }
 
   if (new_param_pattern.Is<SemIR::AddrPattern>()) {
-    new_param_pattern = context.insts().Get(
-        new_param_pattern.As<SemIR::AddrPattern>().inner_id);
-    prev_param_pattern = context.insts().Get(
-        prev_param_pattern.As<SemIR::AddrPattern>().inner_id);
+    new_param_pattern_id = new_param_pattern.As<SemIR::AddrPattern>().inner_id;
+    new_param_pattern = context.insts().Get(new_param_pattern_id);
+    prev_param_pattern_id =
+        prev_param_pattern.As<SemIR::AddrPattern>().inner_id;
+    prev_param_pattern = context.insts().Get(prev_param_pattern_id);
     if (new_param_pattern.kind() != prev_param_pattern.kind()) {
       emit_diagnostic();
       return false;
@@ -243,10 +248,12 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
   }
 
   if (new_param_pattern.Is<SemIR::AnyParamPattern>()) {
-    new_param_pattern = context.insts().Get(
-        new_param_pattern.As<SemIR::ValueParamPattern>().subpattern_id);
-    prev_param_pattern = context.insts().Get(
-        prev_param_pattern.As<SemIR::ValueParamPattern>().subpattern_id);
+    new_param_pattern_id =
+        new_param_pattern.As<SemIR::ValueParamPattern>().subpattern_id;
+    new_param_pattern = context.insts().Get(new_param_pattern_id);
+    prev_param_pattern_id =
+        prev_param_pattern.As<SemIR::ValueParamPattern>().subpattern_id;
+    prev_param_pattern = context.insts().Get(prev_param_pattern_id);
     if (new_param_pattern.kind() != prev_param_pattern.kind()) {
       emit_diagnostic();
       return false;
@@ -267,8 +274,8 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
     return true;
   }
 
-  auto prev_param_type_id = SemIR::GetTypeInSpecific(
-      context.sem_ir(), prev_specific_id, prev_param_pattern.type_id());
+  auto prev_param_type_id = SemIR::GetTypeOfInstInSpecific(
+      context.sem_ir(), prev_specific_id, prev_param_pattern_id);
   if (!context.types().AreEqualAcrossDeclarations(new_param_pattern.type_id(),
                                                   prev_param_type_id)) {
     if (!diagnose) {
@@ -280,9 +287,11 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
                       Diagnostics::BoolAsSelect, int32_t, SemIR::TypeId,
                       SemIR::TypeId);
     context.emitter()
-        .Build(new_param_pattern_id, RedeclParamDiffersType, is_implicit_param,
-               param_index + 1, prev_param_type_id, new_param_pattern.type_id())
-        .Note(prev_param_pattern_id, RedeclParamPrevious, is_implicit_param)
+        .Build(orig_new_param_pattern_id, RedeclParamDiffersType,
+               is_implicit_param, param_index + 1, prev_param_type_id,
+               new_param_pattern.type_id())
+        .Note(orig_prev_param_pattern_id, RedeclParamPrevious,
+              is_implicit_param)
         .Emit();
     return false;
   }

+ 54 - 44
toolchain/check/pattern_match.cpp

@@ -91,25 +91,33 @@ class MatchContext {
   // equal to `context.insts().GetLocId(entry.pattern_id)`.
   auto DoEmitPatternMatch(Context& context,
                           SemIR::AnyBindingPattern binding_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context, SemIR::AddrPattern addr_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context,
                           SemIR::ValueParamPattern param_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context,
                           SemIR::RefParamPattern param_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context,
                           SemIR::OutParamPattern param_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context,
                           SemIR::ReturnSlotPattern return_slot_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context, SemIR::VarPattern var_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
   auto DoEmitPatternMatch(Context& context, SemIR::TuplePattern tuple_pattern,
-                          SemIR::LocId pattern_loc_id, WorkItem entry) -> void;
+                          SemIR::InstId pattern_inst_id, WorkItem entry)
+      -> void;
 
   // The stack of work to be processed.
   llvm::SmallVector<WorkItem> stack_;
@@ -192,7 +200,7 @@ static auto InsertHere(Context& context, SemIR::ExprRegionId region_id)
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::AnyBindingPattern binding_pattern,
-                                      SemIR::LocId /*pattern_loc_id*/,
+                                      SemIR::InstId /*pattern_inst_id*/,
                                       MatchContext::WorkItem entry) -> void {
   if (kind_ == MatchKind::Caller) {
     CARBON_CHECK(binding_pattern.kind == SemIR::SymbolicBindingPattern::Kind,
@@ -233,7 +241,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::AddrPattern addr_pattern,
-                                      SemIR::LocId /*pattern_loc_id*/,
+                                      SemIR::InstId /*pattern_inst_id*/,
                                       WorkItem entry) -> void {
   CARBON_CHECK(kind_ != MatchKind::Local);
   if (kind_ == MatchKind::Callee) {
@@ -272,7 +280,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::ValueParamPattern param_pattern,
-                                      SemIR::LocId pattern_loc_id,
+                                      SemIR::InstId pattern_inst_id,
                                       WorkItem entry) -> void {
   switch (kind_) {
     case MatchKind::Caller: {
@@ -287,8 +295,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
         results_.push_back(ConvertToValueOfType(
             context, context.insts().GetLocId(entry.scrutinee_id),
             entry.scrutinee_id,
-            SemIR::GetTypeInSpecific(context.sem_ir(), callee_specific_id_,
-                                     param_pattern.type_id)));
+            SemIR::GetTypeOfInstInSpecific(
+                context.sem_ir(), callee_specific_id_, pattern_inst_id)));
       }
       // Do not traverse farther, because the caller side of the pattern
       // ends here.
@@ -299,7 +307,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
       param_pattern.index = NextRuntimeIndex();
       ReplaceInstBeforeConstantUse(context, entry.pattern_id, param_pattern);
       auto param_id = AddInst<SemIR::ValueParam>(
-          context, pattern_loc_id,
+          context, context.insts().GetLocId(pattern_inst_id),
           {.type_id = param_pattern.type_id,
            .index = param_pattern.index,
            .pretty_name_id = SemIR::GetPrettyNameFromPatternId(
@@ -317,7 +325,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::RefParamPattern param_pattern,
-                                      SemIR::LocId pattern_loc_id,
+                                      SemIR::InstId pattern_inst_id,
                                       WorkItem entry) -> void {
   switch (kind_) {
     case MatchKind::Caller: {
@@ -340,7 +348,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
       param_pattern.index = NextRuntimeIndex();
       ReplaceInstBeforeConstantUse(context, entry.pattern_id, param_pattern);
       auto param_id = AddInst<SemIR::RefParam>(
-          context, pattern_loc_id,
+          context, context.insts().GetLocId(pattern_inst_id),
           {.type_id = param_pattern.type_id,
            .index = param_pattern.index,
            .pretty_name_id = SemIR::GetPrettyNameFromPatternId(
@@ -358,7 +366,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::OutParamPattern param_pattern,
-                                      SemIR::LocId pattern_loc_id,
+                                      SemIR::InstId pattern_inst_id,
                                       WorkItem entry) -> void {
   switch (kind_) {
     case MatchKind::Caller: {
@@ -368,9 +376,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
           param_pattern.index.index);
       CARBON_CHECK(entry.scrutinee_id.has_value());
       CARBON_CHECK(context.insts().Get(entry.scrutinee_id).type_id() ==
-                   SemIR::GetTypeInSpecific(context.sem_ir(),
-                                            callee_specific_id_,
-                                            param_pattern.type_id));
+                   SemIR::GetTypeOfInstInSpecific(
+                       context.sem_ir(), callee_specific_id_, pattern_inst_id));
       results_.push_back(entry.scrutinee_id);
       // Do not traverse farther, because the caller side of the pattern
       // ends here.
@@ -383,7 +390,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
       param_pattern.index = NextRuntimeIndex();
       ReplaceInstBeforeConstantUse(context, entry.pattern_id, param_pattern);
       auto param_id = AddInst<SemIR::OutParam>(
-          context, pattern_loc_id,
+          context, context.insts().GetLocId(pattern_inst_id),
           {.type_id = param_pattern.type_id,
            .index = param_pattern.index,
            .pretty_name_id = SemIR::GetPrettyNameFromPatternId(
@@ -401,10 +408,10 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
 
 auto MatchContext::DoEmitPatternMatch(
     Context& context, SemIR::ReturnSlotPattern return_slot_pattern,
-    SemIR::LocId pattern_loc_id, WorkItem entry) -> void {
+    SemIR::InstId pattern_inst_id, WorkItem entry) -> void {
   CARBON_CHECK(kind_ == MatchKind::Callee);
   auto return_slot_id = AddInst<SemIR::ReturnSlot>(
-      context, pattern_loc_id,
+      context, context.insts().GetLocId(pattern_inst_id),
       {.type_id = return_slot_pattern.type_id,
        .type_inst_id = return_slot_pattern.type_inst_id,
        .storage_id = entry.scrutinee_id});
@@ -417,7 +424,7 @@ auto MatchContext::DoEmitPatternMatch(
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::VarPattern var_pattern,
-                                      SemIR::LocId pattern_loc_id,
+                                      SemIR::InstId pattern_inst_id,
                                       WorkItem entry) -> void {
   auto storage_id = SemIR::InstId::None;
   switch (kind_) {
@@ -439,7 +446,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
     }
     case MatchKind::Caller: {
       storage_id = AddInstWithCleanup<SemIR::TemporaryStorage>(
-          context, pattern_loc_id, {.type_id = var_pattern.type_id});
+          context, context.insts().GetLocId(pattern_inst_id),
+          {.type_id = var_pattern.type_id});
       CARBON_CHECK(entry.scrutinee_id.has_value());
       break;
     }
@@ -451,11 +459,11 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
     context.global_init().Resume();
   }
   if (entry.scrutinee_id.has_value()) {
-    auto init_id =
-        Initialize(context, pattern_loc_id, storage_id, entry.scrutinee_id);
+    auto loc_id = context.insts().GetLocId(pattern_inst_id);
+    auto init_id = Initialize(context, loc_id, storage_id, entry.scrutinee_id);
     // TODO: Consider using different instruction kinds for assignment
     // versus initialization.
-    AddInst<SemIR::Assign>(context, pattern_loc_id,
+    AddInst<SemIR::Assign>(context, loc_id,
                            {.lhs_id = storage_id, .rhs_id = init_id});
   }
   AddWork(
@@ -467,7 +475,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
 
 auto MatchContext::DoEmitPatternMatch(Context& context,
                                       SemIR::TuplePattern tuple_pattern,
-                                      SemIR::LocId pattern_loc_id,
+                                      SemIR::InstId pattern_inst_id,
                                       WorkItem entry) -> void {
   if (tuple_pattern.type_id == SemIR::ErrorInst::SingletonTypeId) {
     return;
@@ -483,7 +491,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
       };
   if (!entry.scrutinee_id.has_value()) {
     CARBON_CHECK(kind_ == MatchKind::Callee);
-    context.TODO(pattern_loc_id,
+    context.TODO(pattern_inst_id,
                  "Support patterns besides bindings in parameter list");
     return;
   }
@@ -496,7 +504,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
                         "tuple pattern expects {0} element{0:s}, but tuple "
                         "literal has {1}",
                         Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);
-      context.emitter().Emit(pattern_loc_id, TuplePatternSizeDoesntMatchLiteral,
+      context.emitter().Emit(pattern_inst_id,
+                             TuplePatternSizeDoesntMatchLiteral,
                              subpattern_ids.size(), subscrutinee_ids.size());
       return;
     }
@@ -505,7 +514,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
   }
 
   auto converted_scrutinee = ConvertToValueOrRefOfType(
-      context, pattern_loc_id, entry.scrutinee_id, tuple_pattern.type_id);
+      context, context.insts().GetLocId(pattern_inst_id), entry.scrutinee_id,
+      tuple_pattern.type_id);
   if (auto scrutinee_value =
           context.insts().TryGetAs<SemIR::TupleValue>(converted_scrutinee)) {
     add_all_subscrutinees(
@@ -541,44 +551,44 @@ auto MatchContext::EmitPatternMatch(Context& context,
           builder.Note(entry.pattern_id, InCallToFunctionParam);
         }
       });
-  auto pattern = context.insts().GetWithLocId(entry.pattern_id);
-  CARBON_KIND_SWITCH(pattern.inst) {
+  auto pattern = context.insts().Get(entry.pattern_id);
+  CARBON_KIND_SWITCH(pattern) {
     case SemIR::BindingPattern::Kind:
     case SemIR::SymbolicBindingPattern::Kind: {
-      DoEmitPatternMatch(context, pattern.inst.As<SemIR::AnyBindingPattern>(),
-                         pattern.loc_id, entry);
+      DoEmitPatternMatch(context, pattern.As<SemIR::AnyBindingPattern>(),
+                         entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::AddrPattern addr_pattern): {
-      DoEmitPatternMatch(context, addr_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, addr_pattern, entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::ValueParamPattern param_pattern): {
-      DoEmitPatternMatch(context, param_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, param_pattern, entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::RefParamPattern param_pattern): {
-      DoEmitPatternMatch(context, param_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, param_pattern, entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::OutParamPattern param_pattern): {
-      DoEmitPatternMatch(context, param_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, param_pattern, entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::ReturnSlotPattern return_slot_pattern): {
-      DoEmitPatternMatch(context, return_slot_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, return_slot_pattern, entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::VarPattern var_pattern): {
-      DoEmitPatternMatch(context, var_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, var_pattern, entry.pattern_id, entry);
       break;
     }
     case CARBON_KIND(SemIR::TuplePattern tuple_pattern): {
-      DoEmitPatternMatch(context, tuple_pattern, pattern.loc_id, entry);
+      DoEmitPatternMatch(context, tuple_pattern, entry.pattern_id, entry);
       break;
     }
     default: {
-      CARBON_FATAL("Inst kind not handled: {0}", pattern.inst.kind());
+      CARBON_FATAL("Inst kind not handled: {0}", pattern.kind());
     }
   }
 }

+ 4 - 6
toolchain/lower/file_context.cpp

@@ -215,13 +215,11 @@ auto FileContext::BuildFunctionTypeInfo(const SemIR::Function& function,
                                         /*isVarArg=*/false)};
   }
 
-  // TODO nit: add is_symbolic() to type_id to forward to
-  // type_id.AsConstantId().is_symbolic(). Update call below too.
   auto get_llvm_type = [&](SemIR::TypeId type_id) -> llvm::Type* {
     if (!type_id.has_value()) {
       return nullptr;
     }
-    return GetType(SemIR::GetTypeInSpecific(sem_ir(), specific_id, type_id));
+    return GetType(type_id);
   };
 
   // TODO: expose the `Call` parameter patterns in `Function`, and use them here
@@ -267,8 +265,8 @@ auto FileContext::BuildFunctionTypeInfo(const SemIR::Function& function,
     if (!param_pattern_info) {
       continue;
     }
-    auto param_type_id = SemIR::GetTypeInSpecific(
-        sem_ir(), specific_id, param_pattern_info->inst.type_id);
+    auto param_type_id = SemIR::GetTypeOfInstInSpecific(
+        sem_ir(), specific_id, param_pattern_info->inst_id);
     CARBON_CHECK(
         !param_type_id.AsConstantId().is_symbolic(),
         "Found symbolic type id after resolution when lowering type {0}.",
@@ -412,7 +410,7 @@ auto FileContext::BuildFunctionBody(SemIR::FunctionId function_id,
       ++param_index;
     } else {
       param_value = llvm::PoisonValue::get(GetType(
-          SemIR::GetTypeInSpecific(sem_ir(), specific_id, param_inst.type_id)));
+          SemIR::GetTypeOfInstInSpecific(sem_ir(), specific_id, param_id)));
     }
     // The value of the parameter is the value of the argument.
     function_lowering.SetLocal(param_id, param_value);

+ 2 - 2
toolchain/lower/handle_call.cpp

@@ -442,8 +442,8 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
 
   std::vector<llvm::Value*> args;
 
-  auto inst_type_id = SemIR::GetTypeInSpecific(
-      context.sem_ir(), context.specific_id(), inst.type_id);
+  auto inst_type_id = SemIR::GetTypeOfInstInSpecific(
+      context.sem_ir(), context.specific_id(), inst_id);
 
   if (SemIR::ReturnTypeInfo::ForType(context.sem_ir(), inst_type_id)
           .has_return_slot()) {

+ 1 - 2
toolchain/sem_ir/function.cpp

@@ -93,8 +93,7 @@ auto Function::GetDeclaredReturnType(const File& file,
   if (!return_slot_pattern_id.has_value()) {
     return TypeId::None;
   }
-  return GetTypeInSpecific(file, specific_id,
-                           file.insts().Get(return_slot_pattern_id).type_id());
+  return GetTypeOfInstInSpecific(file, specific_id, return_slot_pattern_id);
 }
 
 }  // namespace Carbon::SemIR

+ 6 - 4
toolchain/sem_ir/generic.cpp

@@ -92,10 +92,12 @@ auto GetConstantValueInSpecific(const File& sem_ir, SpecificId specific_id,
                                sem_ir.constant_values().Get(inst_id));
 }
 
-auto GetTypeInSpecific(const File& sem_ir, SpecificId specific_id,
-                       TypeId type_id) -> TypeId {
-  return TypeId::ForTypeConstant(GetConstantInSpecific(
-      sem_ir, specific_id, sem_ir.types().GetConstantId(type_id)));
+auto GetTypeOfInstInSpecific(const File& sem_ir, SpecificId specific_id,
+                             InstId inst_id) -> TypeId {
+  auto type_id = sem_ir.insts().Get(inst_id).type_id();
+  auto const_id = sem_ir.types().GetConstantId(type_id);
+  auto specific_const_id = GetConstantInSpecific(sem_ir, specific_id, const_id);
+  return TypeId::ForTypeConstant(specific_const_id);
 }
 
 }  // namespace Carbon::SemIR

+ 5 - 5
toolchain/sem_ir/generic.h

@@ -157,11 +157,11 @@ auto GetConstantInSpecific(const File& sem_ir, SpecificId specific_id,
 auto GetConstantValueInSpecific(const File& sem_ir, SpecificId specific_id,
                                 InstId inst_id) -> ConstantId;
 
-// Gets the substituted value of a potentially generic type within a specific.
-// Note that this does not perform substitution, and will return `None` if
-// the substituted type is not yet known.
-auto GetTypeInSpecific(const File& sem_ir, SpecificId specific_id,
-                       TypeId type_id) -> TypeId;
+// Gets the substituted type of an instruction within a specific. Note that this
+// does not perform substitution, and will return `None` if the substituted type
+// is not yet known.
+auto GetTypeOfInstInSpecific(const File& sem_ir, SpecificId specific_id,
+                             InstId inst_id) -> TypeId;
 
 }  // namespace Carbon::SemIR