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

Code before:
      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::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);
      }

Review comment (suggestion):
This has changed the behaviour of the other builtin functions that it's below in this switch, no?
Did you try running file_test?
Also, this change should come with some new tests (probably in check/ for compile-time use and in lower/ for run-time use).

Code after:
  }
  CARBON_DIAGNOSTIC(FacetTypeRequiredForTypeAndOperator, Error,
                    "non-facet type {0} combined with `&` operator",
                    SemIR::TypeId);
  // TODO: Find a location for the lhs or rhs specifically, instead of
  // the whole thing. If that's not possible we can change the text to
  // 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]);
    }