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

Code before:
static auto RebuildInitAsValue(EvalContext& eval_context, SemIR::Inst inst,
                               SemIR::InstKind value_kind)
    -> SemIR::ConstantId {
  return TransformIfFieldsAreConstant(
      eval_context, inst,
      [&](SemIR::AnyAggregateInit result) {
        return SemIR::AnyAggregateValue{.kind = value_kind,
                                        .type_id = result.type_id,
                                        .elements_id = result.elements_id};
      },
      &SemIR::AnyAggregateInit::type_id, &SemIR::AnyAggregateInit::elements_id);
}

// Performs an access into an aggregate, retrieving the specified element.
static auto PerformAggregateAccess(EvalContext& eval_context, SemIR::Inst inst)
    -> SemIR::ConstantId {
  auto access_inst = inst.As<SemIR::AnyAggregateAccess>();
  Phase phase = Phase::Template;
  if (ReplaceFieldWithConstantValue(eval_context, &access_inst,
                                    &SemIR::AnyAggregateAccess::aggregate_id,
                                    &phase)) {
    auto aggregate_id = access_inst.aggregate_id;
    CARBON_CHECK(aggregate_id.is_valid());
    if (auto aggregate =
            eval_context.insts().TryGetAs<SemIR::AnyAggregateValue>(
                aggregate_id)) {
      auto elements = eval_context.inst_blocks().Get(aggregate->elements_id);
      auto index = static_cast<size_t>(access_inst.index.index);
      CARBON_CHECK(index < elements.size(), "Access out of bounds.");
      // `Phase` is not used here. If this element is a template constant, then
      // so is the result of indexing, even if the aggregate also contains a
      // symbolic context.
      return eval_context.GetConstantValue(elements[index]);
    } else {
      CARBON_CHECK(phase != Phase::Template,
                   "Failed to evaluate template constant {0}", inst);
    }
    return MakeConstantResult(eval_context.context(), access_inst, phase);
  }
  return MakeNonConstantResult(phase);
}

// Performs an index into a homogeneous aggregate, retrieving the specified
// element.
static auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)
    -> SemIR::ConstantId {
  Phase phase = Phase::Template;
  auto index_id = GetConstantValue(eval_context, inst.index_id, &phase);

  if (!index_id.is_valid()) {
    return MakeNonConstantResult(phase);

Review comment (bug):
Optional: this `CHECK` seems redundant given that the previous function call establishes this as a postcondition and the `TryGetAs` call will also `CHECK`-fail if the ID is invalid.
```suggestion
    if (auto aggregate =
            eval_context.insts().TryGetAs<SemIR::AnyAggregateValue>(
                access_inst.aggregate_id)) {
```

Code after:
static auto RebuildInitAsValue(EvalContext& eval_context, SemIR::Inst inst,
                               SemIR::InstKind value_kind)
    -> SemIR::ConstantId {
  return TransformIfFieldsAreConstant(
      eval_context, inst,
      [&](SemIR::AnyAggregateInit result) {
        return SemIR::AnyAggregateValue{.kind = value_kind,
                                        .type_id = result.type_id,
                                        .elements_id = result.elements_id};
      },
      &SemIR::AnyAggregateInit::type_id, &SemIR::AnyAggregateInit::elements_id);
}

// Performs an access into an aggregate, retrieving the specified element.
static auto PerformAggregateAccess(EvalContext& eval_context, SemIR::Inst inst)
    -> SemIR::ConstantId {
  auto access_inst = inst.As<SemIR::AnyAggregateAccess>();
  Phase phase = Phase::Template;
  if (ReplaceFieldWithConstantValue(eval_context, &access_inst,
                                    &SemIR::AnyAggregateAccess::aggregate_id,
                                    &phase)) {
    if (auto aggregate =
            eval_context.insts().TryGetAs<SemIR::AnyAggregateValue>(
                access_inst.aggregate_id)) {
      auto elements = eval_context.inst_blocks().Get(aggregate->elements_id);
      auto index = static_cast<size_t>(access_inst.index.index);
      CARBON_CHECK(index < elements.size(), "Access out of bounds.");
      // `Phase` is not used here. If this element is a template constant, then
      // so is the result of indexing, even if the aggregate also contains a
      // symbolic context.
      return eval_context.GetConstantValue(elements[index]);
    } else {
      CARBON_CHECK(phase != Phase::Template,
                   "Failed to evaluate template constant {0}", inst);
    }
    return MakeConstantResult(eval_context.context(), access_inst, phase);
  }
  return MakeNonConstantResult(phase);
}

// Performs an index into a homogeneous aggregate, retrieving the specified
// element.
static auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)
    -> SemIR::ConstantId {
  Phase phase = Phase::Template;
  auto index_id = GetConstantValue(eval_context, inst.index_id, &phase);

  if (!index_id.is_valid()) {
    return MakeNonConstantResult(phase);
  }
  auto index = eval_context.insts().TryGetAs<SemIR::IntValue>(index_id);