diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 4c2a44cae19..eb03ff04162 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -11729,7 +11729,6 @@ bool ConstraintSystem::resolveKeyPath(TypeVariableType *typeVar, auto root = args.front(); auto value = getKeyPathValueType(keyPath); - // Make sure that key path always gets a chance to infer its // value type from the member chain. if (!value->isEqual(args.back())) { @@ -12212,6 +12211,19 @@ ConstraintSystem::simplifyKeyPathConstraint( bool definitelyKeyPathType = false; bool resolveAsMultiArgFuncFix = false; + auto formUnsolved = [&]() -> SolutionKind { + if (flags.contains(TMF_GenerateConstraints)) { + addUnsolvedConstraint(Constraint::create( + *this, ConstraintKind::KeyPath, keyPathTy, rootTy, valueTy, + locator.getBaseLocator(), componentTypeVars)); + return SolutionKind::Solved; + } + return SolutionKind::Unsolved; + }; + + if (keyPathTy->isTypeVariableOrMember()) + return formUnsolved(); + auto tryMatchRootAndValueFromType = [&](Type type, bool allowPartial = true) -> bool { Type boundRoot = Type(), boundValue = Type(); @@ -12493,60 +12505,19 @@ ConstraintSystem::simplifyKeyPathConstraint( kpDecl = getASTContext().getWritableKeyPathDecl(); } - auto formUnsolved = [&]() { - addUnsolvedConstraint(Constraint::create( - *this, ConstraintKind::KeyPath, keyPathTy, rootTy, valueTy, - locator.getBaseLocator(), componentTypeVars)); - }; - auto loc = locator.getBaseLocator(); if (definitelyFunctionType) { increaseScore(SK_FunctionConversion, locator); return SolutionKind::Solved; } else if (!anyComponentsUnresolved || (definitelyKeyPathType && capability == ReadOnly)) { - // If key path is connected to a disjunction (i.e. through coercion - // or used as an argument to a function/subscipt call) it cannot be - // bound until the choice is selected because it's undetermined - // until then whether key path is implicitly converted to a function - // type or not. - // - // \code - // struct Data { - // var value: Int = 42 - // } - // - // func test(_: S, _: (S.Element) -> Int) {} - // func test(_: C, _: (C.Element) -> Int) {} - // - // func test(arr: [Data]) { - // test(arr, \Data.value) - // } - // \endcode - // - // In this example if we did allow to bind the key path before - // an overload of `test` is selected, we'd end up with no solutions - // because the type of the key path expression is actually: '(Data) -> Int' - // and not 'WritableKeyPath`. - auto *typeVar = keyPathTy->getAs(); - if (typeVar && findConstraintThroughOptionals( - typeVar, OptionalWrappingDirection::Unwrap, - [&](Constraint *match, TypeVariableType *) { - return match->getKind() == - ConstraintKind::ApplicableFunction || - match->getKind() == ConstraintKind::Disjunction; - })) { - formUnsolved(); - } else { - auto resolvedKPTy = - BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy}); - return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, - subflags, loc); - } - } else { - formUnsolved(); + auto resolvedKPTy = + BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy}); + return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags, + loc); } - return SolutionKind::Solved; + + return formUnsolved(); } ConstraintSystem::SolutionKind