@@ -96,7 +96,7 @@ bool BindingSet::isDelayed() const {
96
96
97
97
// Delay key path literal type binding until there is at least
98
98
// one contextual binding (or default is promoted into a binding).
99
- if (TypeVar->getImpl ().isKeyPathType () && Bindings .empty ())
99
+ if (TypeVar->getImpl ().isKeyPathType () && !Defaults .empty ())
100
100
return true ;
101
101
102
102
if (isHole ()) {
@@ -178,7 +178,7 @@ bool BindingSet::isPotentiallyIncomplete() const {
178
178
// contextual type or key path is resolved enough to infer
179
179
// capability and promote default into a binding.
180
180
if (TypeVar->getImpl ().isKeyPathType ())
181
- return Bindings .empty ();
181
+ return !Defaults .empty ();
182
182
183
183
// If current type variable is associated with a code completion token
184
184
// it's possible that it doesn't have enough contextual information
@@ -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 ())
@@ -496,6 +531,24 @@ void BindingSet::inferTransitiveBindings(
496
531
}
497
532
}
498
533
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
+
499
552
void BindingSet::finalize (
500
553
llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings) {
501
554
inferTransitiveBindings (inferredBindings);
@@ -538,6 +591,84 @@ void BindingSet::finalize(
538
591
}
539
592
}
540
593
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
+
541
672
if (CS.shouldAttemptFixes () &&
542
673
locator->isLastElement <LocatorPathElt::UnresolvedMemberChainResult>()) {
543
674
// Let's see whether this chain is valid, if it isn't then to avoid
@@ -795,6 +926,12 @@ llvm::Optional<BindingSet> ConstraintSystem::determineBestBindings(
795
926
auto isViableForRanking = [this ](const BindingSet &bindings) -> bool {
796
927
auto *typeVar = bindings.getTypeVariable ();
797
928
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
+
798
935
// Type variable representing a base of unresolved member chain should
799
936
// always be considered viable for ranking since it's allow to infer
800
937
// types from transitive protocol requirements.
@@ -886,60 +1023,6 @@ void PotentialBindings::addDefault(Constraint *constraint) {
886
1023
887
1024
void BindingSet::addDefault (Constraint *constraint) {
888
1025
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
-
943
1026
Defaults.insert ({defaultTy->getCanonicalType (), constraint});
944
1027
}
945
1028
0 commit comments