Repository: apple/swift
File: lib/Sema/ConstraintSystem.cpp (C++)

Code before:
  } else {
    // If we didn't resolve an overload for the callee, we should be dealing
    // with a call of an arbitrary function expr.
    if (auto *call = getAsExpr<CallExpr>(anchor)) {
      rawFnType = getType(call->getFn());

      // If callee couldn't be resolved due to expression
      // issues e.g. it's a reference to an invalid member
      // let's just return here.
      if (simplifyType(rawFnType)->is<ErrorType>())
        return std::nullopt;

      // A tuple construction is spelled in the AST as a function call, but
      // is really more like a tuple conversion.
      if (auto metaTy = simplifyType(rawFnType)->getAs<MetatypeType>()) {
        if (metaTy->getInstanceType()->is<TupleType>())
          return std::nullopt;
      }

      assert(!shouldHaveDirectCalleeOverload(call) &&
             "Should we have resolved a callee for this?");
    } else if (auto *keyPath = getAsExpr<KeyPathExpr>(anchor)) {
       // FIX for #85942: Handle KeyPath application diagnostics.
       auto path = locator->getPath();

       for (const auto &elt : path) {
         if (auto componentElt = elt.getAs<LocatorPathElt::KeyPathComponent>()) {
           auto componentIndex = componentElt->getIndex();
           auto &component = keyPath->getComponents()[componentIndex];

           argList = component.getArgs();

           if (!argList)
             return std::nullopt;

           auto *componentLoc = getConstraintLocator(
               anchor, path.take_front((&elt - path.begin()) + 1));

           if (auto selected = getOverloadChoiceIfAvailable(componentLoc)) {
             choice = selected->choice;
             rawFnType = selected->adjustedOpenedType;
           }

           break;
         }
       }

       if (!rawFnType || !argList)
         return std::nullopt;
    } else {
      return std::nullopt;

Review comment (suggestion):
This is closer but not the approach I had in mind. Take a look at `getCalleeLocator` - it's supposed to produce a locator that would be used to retrieve an overload - in your example, the fix points at `key path component #3` which is an Apply component, and calling `getCalleeLocator` on that locator should produce a locator for component `#2` instead because that's the member that is being apply. I think once you fix that everything should just work.

Code after:
  } else {
    // If we didn't resolve an overload for the callee, we should be dealing
    // with a call of an arbitrary function expr.
    auto *call = castToExpr<CallExpr>(anchor);
    rawFnType = getType(call->getFn());

    // If callee couldn't be resolved due to expression
    // issues e.g. it's a reference to an invalid member
    // let's just return here.
    if (simplifyType(rawFnType)->is<ErrorType>())
      return std::nullopt;

    // A tuple construction is spelled in the AST as a function call, but
    // is really more like a tuple conversion.
    if (auto metaTy = simplifyType(rawFnType)->getAs<MetatypeType>()) {
      if (metaTy->getInstanceType()->is<TupleType>())
        return std::nullopt;
    }

    assert(!shouldHaveDirectCalleeOverload(call) &&
             "Should we have resolved a callee for this?");
  }

  // Try to resolve the function type by loading lvalues and looking through
  // optional types, which can occur for expressions like `fn?(5)`.
  auto *fnType = simplifyType(rawFnType)
                     ->getRValueType()
                     ->lookThroughAllOptionalTypes()
                     ->getAs<FunctionType>();
  if (!fnType)
    return std::nullopt;

  // Resolve the interface type for the function. Note that this may not be a
  // function type, for example it could be a generic parameter.
  Type fnInterfaceType;
  auto *callee = choice ? choice->getDeclOrNull() : nullptr;
  if (callee && callee->hasInterfaceType()) {
    // If we have a callee with an interface type, we can use it. This is
    // preferable to simplifyType for the function, as this will allow us to get
    // a GenericFunctionType for generic decls.
    //
    // Note that it's possible to find a callee without an interface type. This
    // can happen for example with closure parameters, where the interface type
    // isn't set until the solution is applied. In that case, use simplifyType.
    fnInterfaceType = callee->getInterfaceType();

    // Strip off the curried self parameter if necessary.
    if (hasAppliedSelf(*this, *choice))
      fnInterfaceType = fnInterfaceType->castTo<AnyFunctionType>()->getResult();

#ifndef NDEBUG