@@ -96,7 +96,7 @@ bool BindingSet::isDelayed() const {
9696
9797 // Delay key path literal type binding until there is at least
9898 // one contextual binding (or default is promoted into a binding).
99- if (TypeVar->getImpl ().isKeyPathType () && Bindings .empty ())
99+ if (TypeVar->getImpl ().isKeyPathType () && !Defaults .empty ())
100100 return true ;
101101
102102 if (isHole ()) {
@@ -178,7 +178,7 @@ bool BindingSet::isPotentiallyIncomplete() const {
178178 // contextual type or key path is resolved enough to infer
179179 // capability and promote default into a binding.
180180 if (TypeVar->getImpl ().isKeyPathType ())
181- return Bindings .empty ();
181+ return !Defaults .empty ();
182182
183183 // If current type variable is associated with a code completion token
184184 // it's possible that it doesn't have enough contextual information
@@ -430,6 +430,41 @@ void BindingSet::inferTransitiveBindings(
430430 &inferredBindings) {
431431 using BindingKind = AllowedBindingKind;
432432
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+
433468 for (const auto &entry : Info.SupertypeOf ) {
434469 auto relatedBindings = inferredBindings.find (entry.first );
435470 if (relatedBindings == inferredBindings.end ())
@@ -496,6 +531,24 @@ void BindingSet::inferTransitiveBindings(
496531 }
497532}
498533
534+ static BoundGenericType *getKeyPathType (ASTContext &ctx,
535+ KeyPathCapability capability,
536+ Type rootType, Type valueType) {
537+ switch (capability) {
538+ case KeyPathCapability::ReadOnly:
539+ return BoundGenericType::get (ctx.getKeyPathDecl (), /* parent=*/ Type (),
540+ {rootType, valueType});
541+
542+ case KeyPathCapability::Writable:
543+ return BoundGenericType::get (ctx.getWritableKeyPathDecl (),
544+ /* parent=*/ Type (), {rootType, valueType});
545+
546+ case KeyPathCapability::ReferenceWritable:
547+ return BoundGenericType::get (ctx.getReferenceWritableKeyPathDecl (),
548+ /* parent=*/ Type (), {rootType, valueType});
549+ }
550+ }
551+
499552void BindingSet::finalize (
500553 llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings) {
501554 inferTransitiveBindings (inferredBindings);
@@ -538,6 +591,84 @@ void BindingSet::finalize(
538591 }
539592 }
540593
594+ if (TypeVar->getImpl ().isKeyPathType ()) {
595+ auto &ctx = CS.getASTContext ();
596+
597+ auto *keyPathLoc = TypeVar->getImpl ().getLocator ();
598+ auto *keyPath = castToExpr<KeyPathExpr>(keyPathLoc->getAnchor ());
599+
600+ bool isValid;
601+ llvm::Optional<KeyPathCapability> capability;
602+
603+ std::tie (isValid, capability) = CS.inferKeyPathLiteralCapability (TypeVar);
604+
605+ // Key path literal is not yet sufficiently resolved.
606+ if (isValid && !capability)
607+ return ;
608+
609+ // If the key path is sufficiently resolved we can add inferred binding
610+ // to the set.
611+ SmallSetVector<PotentialBinding, 4 > updatedBindings;
612+ for (const auto &binding : Bindings) {
613+ auto bindingTy = binding.BindingType ->lookThroughAllOptionalTypes ();
614+
615+ assert (isKnownKeyPathType (bindingTy) || bindingTy->is <FunctionType>());
616+
617+ // Functions don't have capability so we can simply add them.
618+ if (bindingTy->is <FunctionType>())
619+ updatedBindings.insert (binding);
620+ }
621+
622+ // Note that even though key path literal maybe be invalid it's
623+ // still the best course of action to use contextual function type
624+ // bindings because they allow to propagate type information from
625+ // the key path into the context, so key path bindings are addded
626+ // only if there is absolutely no other choice.
627+ if (updatedBindings.empty ()) {
628+ auto rootTy = CS.getKeyPathRootType (keyPath);
629+
630+ // A valid key path literal.
631+ if (capability) {
632+ // Note that the binding is formed using root & value
633+ // type variables produced during constraint generation
634+ // because at this point root is already known (otherwise
635+ // inference wouldn't been able to determine key path's
636+ // capability) and we always want to infer value from
637+ // the key path and match it to a contextual type to produce
638+ // better diagnostics.
639+ auto keyPathTy = getKeyPathType (ctx, *capability, rootTy,
640+ CS.getKeyPathValueType (keyPath));
641+ updatedBindings.insert (
642+ {keyPathTy, AllowedBindingKind::Exact, keyPathLoc});
643+ } else if (CS.shouldAttemptFixes ()) {
644+ // If key path is structurally correct and has a resolved root
645+ // type, let's promote the fallback type into a binding because
646+ // root would have been inferred from explicit type already and
647+ // it's benefitial for diagnostics to assign a non-placeholder
648+ // type to key path literal to propagate root/value to the context.
649+ if (!keyPath->hasSingleInvalidComponent () &&
650+ (keyPath->getParsedRoot () ||
651+ !CS.getFixedType (rootTy)->isTypeVariableOrMember ())) {
652+ auto fallback = llvm::find_if (Defaults, [](const auto &entry) {
653+ return entry.second ->getKind () == ConstraintKind::FallbackType;
654+ });
655+ assert (fallback != Defaults.end ());
656+ updatedBindings.insert (
657+ {fallback->first , AllowedBindingKind::Exact, fallback->second });
658+ } else {
659+ updatedBindings.insert (PotentialBinding::forHole (
660+ TypeVar, CS.getConstraintLocator (
661+ keyPath, ConstraintLocator::FallbackType)));
662+ }
663+ }
664+ }
665+
666+ Bindings = std::move (updatedBindings);
667+ Defaults.clear ();
668+
669+ return ;
670+ }
671+
541672 if (CS.shouldAttemptFixes () &&
542673 locator->isLastElement <LocatorPathElt::UnresolvedMemberChainResult>()) {
543674 // Let's see whether this chain is valid, if it isn't then to avoid
@@ -795,6 +926,12 @@ llvm::Optional<BindingSet> ConstraintSystem::determineBestBindings(
795926 auto isViableForRanking = [this ](const BindingSet &bindings) -> bool {
796927 auto *typeVar = bindings.getTypeVariable ();
797928
929+ // Key path root type variable is always viable because it can be
930+ // transitively inferred from key path type during binding set
931+ // finalization.
932+ if (typeVar->getImpl ().isKeyPathRoot ())
933+ return true ;
934+
798935 // Type variable representing a base of unresolved member chain should
799936 // always be considered viable for ranking since it's allow to infer
800937 // types from transitive protocol requirements.
@@ -886,60 +1023,6 @@ void PotentialBindings::addDefault(Constraint *constraint) {
8861023
8871024void BindingSet::addDefault (Constraint *constraint) {
8881025 auto defaultTy = constraint->getSecondType ();
889-
890- if (TypeVar->getImpl ().isKeyPathType () && Bindings.empty ()) {
891- if (constraint->getKind () == ConstraintKind::FallbackType) {
892- auto &ctx = CS.getASTContext ();
893-
894- bool isValid;
895- llvm::Optional<KeyPathCapability> capability;
896-
897- std::tie (isValid, capability) = CS.inferKeyPathLiteralCapability (TypeVar);
898-
899- if (!isValid) {
900- // If one of the references in a key path is invalid let's add
901- // a placeholder binding in diagnostic mode to indicate that
902- // the key path cannot be properly resolved.
903- if (CS.shouldAttemptFixes ()) {
904- addBinding ({PlaceholderType::get (ctx, TypeVar),
905- AllowedBindingKind::Exact, constraint});
906- }
907-
908- // During normal solving the set has to stay empty.
909- return ;
910- }
911-
912- if (capability) {
913- auto *keyPathType = defaultTy->castTo <BoundGenericType>();
914-
915- auto root = keyPathType->getGenericArgs ()[0 ];
916- auto value = keyPathType->getGenericArgs ()[1 ];
917-
918- switch (*capability) {
919- case KeyPathCapability::ReadOnly:
920- break ;
921-
922- case KeyPathCapability::Writable:
923- keyPathType = BoundGenericType::get (ctx.getWritableKeyPathDecl (),
924- /* parent=*/ Type (), {root, value});
925- break ;
926-
927- case KeyPathCapability::ReferenceWritable:
928- keyPathType =
929- BoundGenericType::get (ctx.getReferenceWritableKeyPathDecl (),
930- /* parent=*/ Type (), {root, value});
931- break ;
932- }
933-
934- addBinding ({keyPathType, AllowedBindingKind::Exact, constraint});
935- }
936-
937- // If key path is not yet sufficiently resolved, don't add any
938- // bindings.
939- return ;
940- }
941- }
942-
9431026 Defaults.insert ({defaultTy->getCanonicalType (), constraint});
9441027}
9451028
0 commit comments