@@ -430,6 +430,41 @@ void BindingSet::inferTransitiveBindings(
430
430
&inferredBindings) {
431
431
using BindingKind = AllowedBindingKind;
432
432
433
+ // If the current type variable represents a key path root type
434
+ // let's try to transitively infer its type through bindings of
435
+ // a key path type.
436
+ if (TypeVar->getImpl ().isKeyPathRoot ()) {
437
+ auto *locator = TypeVar->getImpl ().getLocator ();
438
+ if (auto *keyPathTy =
439
+ CS.getType (locator->getAnchor ())->getAs <TypeVariableType>()) {
440
+ auto keyPathBindings = inferredBindings.find (keyPathTy);
441
+ if (keyPathBindings != inferredBindings.end ()) {
442
+ auto &bindings = keyPathBindings->getSecond ();
443
+
444
+ for (auto &binding : bindings.Bindings ) {
445
+ auto bindingTy = binding.BindingType ->lookThroughAllOptionalTypes ();
446
+
447
+ Type inferredRootTy;
448
+ if (isKnownKeyPathType (bindingTy)) {
449
+ // AnyKeyPath doesn't have a root type.
450
+ if (bindingTy->isAnyKeyPath ())
451
+ continue ;
452
+
453
+ auto *BGT = bindingTy->castTo <BoundGenericType>();
454
+ inferredRootTy = BGT->getGenericArgs ()[0 ];
455
+ } else if (auto *fnType = bindingTy->getAs <FunctionType>()) {
456
+ if (fnType->getNumParams () == 1 )
457
+ inferredRootTy = fnType->getParams ()[0 ].getParameterType ();
458
+ }
459
+
460
+ if (inferredRootTy && !inferredRootTy->isTypeVariableOrMember ())
461
+ addBinding (
462
+ binding.withSameSource (inferredRootTy, BindingKind::Exact));
463
+ }
464
+ }
465
+ }
466
+ }
467
+
433
468
for (const auto &entry : Info.SupertypeOf ) {
434
469
auto relatedBindings = inferredBindings.find (entry.first );
435
470
if (relatedBindings == inferredBindings.end ())
@@ -795,6 +830,12 @@ llvm::Optional<BindingSet> ConstraintSystem::determineBestBindings(
795
830
auto isViableForRanking = [this ](const BindingSet &bindings) -> bool {
796
831
auto *typeVar = bindings.getTypeVariable ();
797
832
833
+ // Key path root type variable is always viable because it can be
834
+ // transitively inferred from key path type during binding set
835
+ // finalization.
836
+ if (typeVar->getImpl ().isKeyPathRoot ())
837
+ return true ;
838
+
798
839
// Type variable representing a base of unresolved member chain should
799
840
// always be considered viable for ranking since it's allow to infer
800
841
// types from transitive protocol requirements.
0 commit comments