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

Code before:
    default: {
      CARBON_DIAGNOSTIC(CallToNonCallable, Error,
                        "value of type {0} is not callable", TypeOfInstId);
      context.emitter().Emit(loc_id, CallToNonCallable, callee_id);
      return SemIR::ErrorInst::InstId;
    }
  }
}

auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
                 llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {
  // Try treating the callee as a function first.
  auto callee = GetCallee(context.sem_ir(), callee_id);
  CARBON_KIND_SWITCH(callee) {
    case CARBON_KIND(SemIR::CalleeError _): {
      return SemIR::ErrorInst::InstId;
    }
    case CARBON_KIND(SemIR::CalleeFunction fn): {
      return PerformCallToFunction(context, loc_id, callee_id, fn, arg_ids);
    }
    case CARBON_KIND(SemIR::CalleeNonFunction _): {
      return PerformCallToNonFunction(context, loc_id, callee_id, arg_ids);
    }

    case CARBON_KIND(SemIR::CalleeCppOverloadSet overload): {
      return PerformCallToCppOverloadFunction(context, loc_id,
                                              overload.cpp_overload_set_id,
                                              overload.self_id, arg_ids);
    }
  }
}

}  // namespace Carbon::Check


Review comment (performance):
Hmm.. I find the boundaries to be not so clean any more between the `call` and `overload_resolution`, as we include `call` in `overload_resolution` and vice versa and calling functions back and forth from them. What is the motivation of the change, is it the complexity of the `CppOverloadResolutionResult`?

How about moving this function in `call` instead? Then maybe keep the functionality as is (first perform overload resolution then perform call) and try to simplify the result by passing the args by reference and just returning <instid, callefunction>? Or similar alternatives, so that the responsibilities are kept cleaner.


Code after:
    default: {
      CARBON_DIAGNOSTIC(CallToNonCallable, Error,
                        "value of type {0} is not callable", TypeOfInstId);
      context.emitter().Emit(loc_id, CallToNonCallable, callee_id);
      return SemIR::ErrorInst::InstId;
    }
  }
}

auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
                 llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {
  // Try treating the callee as a function first.
  auto callee = GetCallee(context.sem_ir(), callee_id);
  CARBON_KIND_SWITCH(callee) {
    case CARBON_KIND(SemIR::CalleeError _): {
      return SemIR::ErrorInst::InstId;
    }
    case CARBON_KIND(SemIR::CalleeFunction fn): {
      return PerformCallToFunction(context, loc_id, callee_id, fn, arg_ids);
    }
    case CARBON_KIND(SemIR::CalleeNonFunction _): {
      return PerformCallToNonFunction(context, loc_id, callee_id, arg_ids);
    }

    case CARBON_KIND(SemIR::CalleeCppOverloadSet overload): {
      return PerformCallToCppFunction(context, loc_id,
                                      overload.cpp_overload_set_id,
                                      overload.self_id, arg_ids);
    }
  }
}

}  // namespace Carbon::Check