@@ -602,17 +602,45 @@ void BindingSet::finalize(
602
602
603
603
std::tie (isValid, capability) = CS.inferKeyPathLiteralCapability (TypeVar);
604
604
605
- if (!isValid) {
606
- // If key path is invalid we have to drop all the contextual
607
- // bindings, none of the could be used unless capability is
608
- // known.
609
- Bindings.clear ();
610
-
611
- // If one of the references in a key path is invalid let's add
612
- // a placeholder binding in diagnostic mode to indicate that
613
- // the key path cannot be properly resolved.
614
- if (CS.shouldAttemptFixes ()) {
615
- auto rootTy = CS.getKeyPathRootType (keyPath);
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 ()) {
616
644
// If key path is structurally correct and has a resolved root
617
645
// type, let's promote the fallback type into a binding because
618
646
// root would have been inferred from explicit type already and
@@ -625,52 +653,18 @@ void BindingSet::finalize(
625
653
return entry.second ->getKind () == ConstraintKind::FallbackType;
626
654
});
627
655
assert (fallback != Defaults.end ());
628
- addBinding (
656
+ updatedBindings. insert (
629
657
{fallback->first , AllowedBindingKind::Exact, fallback->second });
630
658
} else {
631
- addBinding (PotentialBinding::forHole (
659
+ updatedBindings. insert (PotentialBinding::forHole (
632
660
TypeVar, CS.getConstraintLocator (
633
661
keyPath, ConstraintLocator::FallbackType)));
634
662
}
635
663
}
636
-
637
- // No need for fallback if key path is invalid.
638
- Defaults.clear ();
639
- return ;
640
664
}
641
665
642
- // If the key path is sufficiently resolved we can add inferred binding
643
- // to the set.
644
- if (capability) {
645
- SmallSetVector<PotentialBinding, 4 > updatedBindings;
646
- for (const auto &binding : Bindings) {
647
- auto bindingTy = binding.BindingType ->lookThroughAllOptionalTypes ();
648
-
649
- assert (isKnownKeyPathType (bindingTy) ||
650
- bindingTy->is <FunctionType>());
651
-
652
- // Functions don't have capability so we can simply add them.
653
- if (bindingTy->is <FunctionType>())
654
- updatedBindings.insert (binding);
655
- }
656
-
657
- // Note that the binding is formed using root & value
658
- // type variables produced during constraint generation
659
- // because at this point root is already known (otherwise
660
- // inference wouldn't been able to determine key path's
661
- // capability) and we always want to infer value from
662
- // the key path and match it to a contextual type to produce
663
- // better diagnostics.
664
- auto keyPathTy =
665
- getKeyPathType (ctx, *capability, CS.getKeyPathRootType (keyPath),
666
- CS.getKeyPathValueType (keyPath));
667
-
668
- updatedBindings.insert (
669
- {keyPathTy, AllowedBindingKind::Exact, keyPathLoc});
670
-
671
- Bindings = std::move (updatedBindings);
672
- Defaults.clear ();
673
- }
666
+ Bindings = std::move (updatedBindings);
667
+ Defaults.clear ();
674
668
675
669
return ;
676
670
}
0 commit comments