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

Code before:
      &context.emitter(), [&](auto& builder) {
        CARBON_DIAGNOSTIC(IncompleteReturnTypeHere, Note,
                          "return type declared here");
        builder.Note(function.return_slot_pattern_id, IncompleteReturnTypeHere);
      });
  return CheckFunctionReturnType(context, loc_id, function, callee_specific_id);
}

// Performs a call where the callee is a function.
static auto PerformCallToFunction(Context& context, SemIR::LocId loc_id,
                                  SemIR::InstId callee_id,
                                  const SemIR::CalleeFunction& callee_function,
                                  llvm::ArrayRef<SemIR::InstId> arg_ids)
    -> SemIR::InstId {
  // If the callee is a generic function, determine the generic argument values
  // for the call.
  auto callee_specific_id = ResolveCalleeInCall(
      context, loc_id, context.functions().Get(callee_function.function_id),
      EntityKind::Function, callee_function.enclosing_specific_id,
      callee_function.self_type_id, callee_function.self_id, arg_ids);
  if (!callee_specific_id) {
    return SemIR::ErrorInst::SingletonInstId;
  }

  if (callee_specific_id->has_value()) {
    callee_id = ResolveCalleeSpecific(context, loc_id, callee_id,
                                      callee_function.self_type_id,
                                      *callee_specific_id);
  }

  // If there is a return slot, build storage for the result.
  SemIR::ReturnTypeInfo return_info = CheckCalleeFunctionReturnType(
      context, loc_id, callee_function.function_id, *callee_specific_id);
  SemIR::InstId return_slot_arg_id = SemIR::InstId::None;
  switch (return_info.init_repr.kind) {
    case SemIR::InitRepr::InPlace:
      // Tentatively put storage for a temporary in the function's return slot.
      // This will be replaced if necessary when we perform initialization.
      return_slot_arg_id = AddInstWithCleanup<SemIR::TemporaryStorage>(
          context, loc_id, {.type_id = return_info.type_id});
      break;
    case SemIR::InitRepr::None:
      // For functions with an implicit return type, the return type is the
      // empty tuple type.
      if (!return_info.type_id.has_value()) {
        return_info.type_id = GetTupleType(context, {});
      }
      break;
    case SemIR::InitRepr::ByCopy:
      break;
    case SemIR::InitRepr::Incomplete:

Review comment (suggestion):
Maybe `BuildCalleeSpecificFunction`, given that this is only for the function case. `Resolve` vs `Build` I could go either way, but the resolve step here is a bit indirect these days (it happens as a consequence of the constant evaluation of the `SpecificFunction`) so `Build` seems maybe a bit clearer.

Code after:
      &context.emitter(), [&](auto& builder) {
        CARBON_DIAGNOSTIC(IncompleteReturnTypeHere, Note,
                          "return type declared here");
        builder.Note(function.return_slot_pattern_id, IncompleteReturnTypeHere);
      });
  return CheckFunctionReturnType(context, loc_id, function, callee_specific_id);
}

// Performs a call where the callee is a function.
static auto PerformCallToFunction(Context& context, SemIR::LocId loc_id,
                                  SemIR::InstId callee_id,
                                  const SemIR::CalleeFunction& callee_function,
                                  llvm::ArrayRef<SemIR::InstId> arg_ids)
    -> SemIR::InstId {
  // If the callee is a generic function, determine the generic argument values
  // for the call.
  auto callee_specific_id = ResolveCalleeInCall(
      context, loc_id, context.functions().Get(callee_function.function_id),
      EntityKind::Function, callee_function.enclosing_specific_id,
      callee_function.self_type_id, callee_function.self_id, arg_ids);
  if (!callee_specific_id) {
    return SemIR::ErrorInst::SingletonInstId;
  }

  if (callee_specific_id->has_value()) {
    callee_id = BuildCalleeSpecificFunction(context, loc_id, callee_id,
                                            callee_function.self_type_id,
                                            *callee_specific_id);
  }

  // If there is a return slot, build storage for the result.
  SemIR::ReturnTypeInfo return_info = CheckCalleeFunctionReturnType(
      context, loc_id, callee_function.function_id, *callee_specific_id);
  SemIR::InstId return_slot_arg_id = SemIR::InstId::None;
  switch (return_info.init_repr.kind) {
    case SemIR::InitRepr::InPlace:
      // Tentatively put storage for a temporary in the function's return slot.
      // This will be replaced if necessary when we perform initialization.
      return_slot_arg_id = AddInstWithCleanup<SemIR::TemporaryStorage>(
          context, loc_id, {.type_id = return_info.type_id});
      break;
    case SemIR::InitRepr::None:
      // For functions with an implicit return type, the return type is the
      // empty tuple type.
      if (!return_info.type_id.has_value()) {
        return_info.type_id = GetTupleType(context, {});
      }
      break;
    case SemIR::InitRepr::ByCopy:
      break;
    case SemIR::InitRepr::Incomplete: