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

Code before:

    case SemIR::BuiltinFunctionKind::TypeCanDestroy: {
      CARBON_CHECK(arg_ids.empty());
      auto id = eval_context.facet_types().Add(
          {.builtin_constraint_mask =
               SemIR::BuiltinConstraintMask::TypeCanDestroy});
      return MakeConstantResult(
          eval_context.context(),
          SemIR::FacetType{.type_id = SemIR::TypeType::TypeId,
                           .facet_type_id = id},
          phase);
    }

    case SemIR::BuiltinFunctionKind::PrimitiveCopy: {
      return context.constant_values().Get(arg_ids[0]);
    }

    case SemIR::BuiltinFunctionKind::PrintChar:
    case SemIR::BuiltinFunctionKind::PrintInt:
    case SemIR::BuiltinFunctionKind::StringAt:{
      //We need both the string and index to be constant
      Phase phase = Phase::Concrete;
      auto str_id = GetConstantValue(eval_context, arg_ids[0], &phase);
      auto index_id = GetConstantValue(eval_context, arg_ids[1], &phase);
      //If either isnt constant, we can't evaluate it at compile time
      if (!str_id.has_value() || !index_id.has_value()) {
        return MakeNonConstantResult(phase);
      }

      auto str_struct = eval_context.insts().TryGetAs<SemIR::StructValue>(str_id);
      if(!str_struct) {
        return MakeNonConstantResult(phase);
      }

      auto elements = eval_context.inst_blocks().Get(str_struct->elements_id);
      if (elements.size() != 2) {
        return MakeNonConstantResult(phase);
      }

      auto ptr_const_id = eval_context.constant_values().Get(elements[0]);
      auto string_literal = eval_context.insts().TryGetAs<SemIR::StringLiteral>(
        eval_context.constant_values().GetInstId(ptr_const_id));
      if (!string_literal){
        return MakeNonConstantResult(phase);
      }
      
      auto string_value = eval_context.sem_ir().string_literal_values().Get(
        string_literal->string_literal_id);
      //Get index value
      auto index_inst = eval_context.insts().TryGetAs<SemIR::IntValue>(index_id);
      if (!index_inst) {

Review comment (suggestion):
I don't think we need to support symbolic strings or indexes, so how about we also return here if phase is not Concrete?

Then we can stop with all the early outs below, and assume we have the concrete expected types, using GetAs instead of TryGetAs etc

Code after:
  // say if it's referring to the left or the right side for the error.
  // The `arg_id` instruction has no location in it for some reason.
  context.emitter().Emit(loc_id, FacetTypeRequiredForTypeAndOperator,
                         context.types().GetTypeIdForTypeInstId(type_arg_id));
  return SemIR::FacetTypeId::None;
}

// Returns a constant for a call to a builtin function.
static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
                                       SemIR::LocId loc_id, SemIR::Call call,
                                       SemIR::BuiltinFunctionKind builtin_kind,
                                       llvm::ArrayRef<SemIR::InstId> arg_ids,
                                       Phase phase) -> SemIR::ConstantId {
  auto& context = eval_context.context();
  switch (builtin_kind) {
    case SemIR::BuiltinFunctionKind::None:
      CARBON_FATAL("Not a builtin function.");

    case SemIR::BuiltinFunctionKind::NoOp:
    case SemIR::BuiltinFunctionKind::TypeDestroy: {
      // Return an empty tuple value.
      auto type_id = GetTupleType(eval_context.context(), {});
      return MakeConstantResult(
          eval_context.context(),
          SemIR::TupleValue{.type_id = type_id,
                            .elements_id = SemIR::InstBlockId::Empty},
          phase);
    }

    case SemIR::BuiltinFunctionKind::TypeCanDestroy: {
      CARBON_CHECK(arg_ids.empty());
      auto id = eval_context.facet_types().Add(
          {.builtin_constraint_mask =
               SemIR::BuiltinConstraintMask::TypeCanDestroy});
      return MakeConstantResult(
          eval_context.context(),
          SemIR::FacetType{.type_id = SemIR::TypeType::TypeId,
                           .facet_type_id = id},
          phase);
    }

    case SemIR::BuiltinFunctionKind::PrimitiveCopy: {
      return context.constant_values().Get(arg_ids[0]);
    }

    case SemIR::BuiltinFunctionKind::StringAt: {
      Phase phase = Phase::Concrete;
      auto str_id = GetConstantValue(eval_context, arg_ids[0], &phase);
      auto index_id = GetConstantValue(eval_context, arg_ids[1], &phase);

      if (phase != Phase::Concrete) {