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

Code before:
auto TryEvalTypedInst<SemIR::SymbolicBindingType>(EvalContext& eval_context,
                                                  SemIR::InstId inst_id,
                                                  SemIR::Inst inst)
    -> SemIR::ConstantId {
  auto bind = inst.As<SemIR::SymbolicBindingType>();

  // If a specific provides a new value for the binding with `entity_name_id`,
  // the SymbolicBindingType is evaluated for that new value.
  const auto& bind_name = eval_context.entity_names().Get(bind.entity_name_id);
  if (bind_name.bind_index().has_value()) {
    if (auto value =
            eval_context.GetCompileTimeBindValue(bind_name.bind_index());
        value.has_value()) {
      auto value_inst_id = eval_context.constant_values().GetInstId(value);

      // A SymbolicBindingType can evaluate to a FacetAccessType if the new
      // value of the entity is a facet value that that does not have a concrete
      // type (a FacetType) and does not have a new EntityName to point to (a
      // BindSymbolicName).
      auto access = SemIR::FacetAccessType{
          .type_id = SemIR::TypeType::TypeId,
          .facet_value_inst_id = value_inst_id,
      };
      return ConvertEvalResultToConstantId(
          eval_context.context(),
          EvalConstantInst(eval_context.context(), access),
          ComputeInstPhase(eval_context.context(), access));
    }
  }

  Phase phase = Phase::Concrete;
  if (!ReplaceTypeWithConstantValue(eval_context, inst_id, &inst, &phase) ||
      !ReplaceAllFieldsWithConstantValues(eval_context, &inst, &phase)) {
    return SemIR::ConstantId::NotConstant;
  }
  // Propagate error phase after getting the constant value for all fields.
  if (phase == Phase::UnknownDueToError) {
    return SemIR::ErrorInst::ConstantId;
  }

  // Copy the updated constant field values into `bind`.
  bind = inst.As<SemIR::SymbolicBindingType>();

  // Evaluation of SymbolicBindingType.
  //
  // Like FacetAccessType, a SymbolicBindingType of a FacetValue just evaluates
  // to the type inside.
  //
  // TODO: Look in ScopeStack with the entity_name_id to find the facet value
  // and get its constant value in the current specific context. The
  // facet_value_inst_id will go away.

Review comment (suggestion):
Could shortcut this a little:
```suggestion
          GetPhase(eval_context.constant_values(), value));
```
... though either way seems OK to me.

Code after:
auto TryEvalTypedInst<SemIR::SymbolicBindingType>(EvalContext& eval_context,
                                                  SemIR::InstId inst_id,
                                                  SemIR::Inst inst)
    -> SemIR::ConstantId {
  // If a specific provides a new value for the binding with `entity_name_id`,
  // the SymbolicBindingType is evaluated for that new value.
  const auto& bind_name = eval_context.entity_names().Get(
      inst.As<SemIR::SymbolicBindingType>().entity_name_id);
  if (bind_name.bind_index().has_value()) {
    if (auto value =
            eval_context.GetCompileTimeBindValue(bind_name.bind_index());
        value.has_value()) {
      auto value_inst_id = eval_context.constant_values().GetInstId(value);

      // A SymbolicBindingType can evaluate to a FacetAccessType if the new
      // value of the entity is a facet value that that does not have a concrete
      // type (a FacetType) and does not have a new EntityName to point to (a
      // BindSymbolicName).
      auto access = SemIR::FacetAccessType{
          .type_id = SemIR::TypeType::TypeId,
          .facet_value_inst_id = value_inst_id,
      };
      return ConvertEvalResultToConstantId(
          eval_context.context(),
          EvalConstantInst(eval_context.context(), access),
          ComputeInstPhase(eval_context.context(), access));
    }
  }

  Phase phase = Phase::Concrete;
  if (!ReplaceTypeWithConstantValue(eval_context, inst_id, &inst, &phase) ||
      !ReplaceAllFieldsWithConstantValues(eval_context, &inst, &phase)) {
    return SemIR::ConstantId::NotConstant;
  }
  // Propagate error phase after getting the constant value for all fields.
  if (phase == Phase::UnknownDueToError) {
    return SemIR::ErrorInst::ConstantId;
  }

  // Evaluation of SymbolicBindingType.
  //
  // Like FacetAccessType, a SymbolicBindingType of a FacetValue just evaluates
  // to the type inside.
  //
  // TODO: Look in ScopeStack with the entity_name_id to find the facet value
  // and get its constant value in the current specific context. The
  // facet_value_inst_id will go away.
  if (auto facet_value = eval_context.insts().TryGetAs<SemIR::FacetValue>(
          inst.As<SemIR::SymbolicBindingType>().facet_value_inst_id)) {
    return eval_context.constant_values().Get(facet_value->type_inst_id);
  }