Repository: carbon-language/carbon-lang
File: toolchain/check/eval.cpp (C++)

Code before:
// If the `InstId` is not provided, the instruction is assumed to be new and
// therefore unattached, so the type is not updated.
static auto ReplaceTypeWithConstantValue(EvalContext& eval_context,
                                         SemIR::InstId inst_id,
                                         SemIR::Inst* inst, Phase* phase)
    -> bool {
  if (inst_id.has_value()) {
    inst->SetType(GetTypeOfInst(eval_context, inst_id, phase));
  }
  return IsConstant(*phase);
}

template <typename InstT>
static auto ReplaceTypeWithConstantValue(EvalContext& eval_context,
                                         SemIR::InstId inst_id, InstT* inst,
                                         Phase* phase) -> bool {
  if (inst_id.has_value()) {
    inst->type_id = GetTypeOfInst(eval_context, inst_id, phase);
  }
  return IsConstant(*phase);
}

static auto ResolveSpecificDeclForInst(EvalContext& eval_context,
                                       const SemIR::Inst& inst) -> void;

// Resolve the specific declaration in the given instruction field. There is an
// overload for any field type that has a GetConstantValue() overload which
// canonicalizes a specific as part of forming its constant value.
static auto ResolveSpecificDeclForField(EvalContext& eval_context,
                                        SemIR::SpecificId specific_id) -> void {
  if (!specific_id.has_value()) {
    return;
  }

  const auto& specific = eval_context.specifics().Get(specific_id);
  const auto& generic = eval_context.generics().Get(specific.generic_id);
  if (!generic.decl_block_id.has_value()) {
    // Impl witness table construction happens before its own generic is
    // finished, in order to make the table's instructions dependent
    // instructions of the Impl's generic. So we can not resolve the specific
    // declaration for such instructions at the time they are created, as the
    // generic's declaration eval block is not yet constructed (with those
    // dependent instructions in it).
    //
    // TODO: Find a way to avoid this early out by making the evaluation of
    // instructions in the witness table that require a specific happen after
    // the generic is complete. Or find a way to limit this just to the impl
    // witness table and ensure the declarations will be resolved.
    return;
  }


Review comment (suggestion):
This looks like it's only called from line 1870, after the definition; is the forward declaration still needed? i.e.:

```suggestion
// Resolve the specific declaration in the given instruction field. There is an
```

Code after:
// therefore unattached, so the type is not updated.
static auto ReplaceTypeWithConstantValue(EvalContext& eval_context,
                                         SemIR::InstId inst_id,
                                         SemIR::Inst* inst, Phase* phase)
    -> bool {
  if (inst_id.has_value()) {
    inst->SetType(GetTypeOfInst(eval_context, inst_id, phase));
  }
  return IsConstant(*phase);
}

template <typename InstT>
static auto ReplaceTypeWithConstantValue(EvalContext& eval_context,
                                         SemIR::InstId inst_id, InstT* inst,
                                         Phase* phase) -> bool {
  if (inst_id.has_value()) {
    inst->type_id = GetTypeOfInst(eval_context, inst_id, phase);
  }
  return IsConstant(*phase);
}

template <typename... T>
struct KindHasGetConstantValueOverload;

template <typename... Types>
struct KindHasGetConstantValueOverload<TypeEnum<Types...>> {
  static constexpr auto Value(TypeEnum<Types...> e) -> bool {
    constexpr auto Values = [] {
      std::array<bool, SemIR::IdKind::NumValues> values = {false};
      ((values[SemIR::IdKind::template For<Types>.ToIndex()] =
            HasGetConstantValueOverload<Types>),
       ...);
      return values;
    }();
    return Values[e.ToIndex()];
  }
};

static auto ResolveSpecificDeclForSpecificId(EvalContext& eval_context,
                                             SemIR::SpecificId specific_id)
    -> void {
  if (!specific_id.has_value()) {
    return;
  }

  const auto& specific = eval_context.specifics().Get(specific_id);
  const auto& generic = eval_context.generics().Get(specific.generic_id);
  if (specific_id == generic.self_specific_id) {
    // Impl witness table construction happens before its generic decl is
    // finish, in order to make the table's instructions dependent
    // instructions of the Impl's generic. But those instructions can refer to