Skip to content

Commit 96415b2

Browse files
committed
[CSBinding] Attempt to join any existing and viable bindings with new binding
Instead of attempting to join only the last recorded supertype binding, let's attempt to join any previously recorded supertype binding with an incoming one to make sure that set contains only the most viable types.
1 parent 84360d9 commit 96415b2

File tree

2 files changed

+37
-24
lines changed

2 files changed

+37
-24
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4706,6 +4706,11 @@ class ConstraintSystem {
47064706
return {type, kind, BindingSource};
47074707
}
47084708

4709+
/// Determine whether this binding could be a viable candidate
4710+
/// to be "joined" with some other binding. It has to be at least
4711+
/// a non-default r-value supertype binding with no type variables.
4712+
bool isViableForJoin() const;
4713+
47094714
static PotentialBinding forHole(TypeVariableType *typeVar,
47104715
ConstraintLocator *locator) {
47114716
return {HoleType::get(typeVar->getASTContext(), typeVar),
@@ -4745,9 +4750,6 @@ class ConstraintSystem {
47454750
/// Whether this type variable has literal bindings.
47464751
LiteralBindingKind LiteralBinding = LiteralBindingKind::None;
47474752

4748-
/// Tracks the position of the last known supertype in the group.
4749-
Optional<unsigned> lastSupertypeIndex;
4750-
47514753
/// A set of all not-yet-resolved type variables this type variable
47524754
/// is a subtype of, supertype of or is equivalent to. This is used
47534755
/// to determine ordering inside of a chain of subtypes to help infer

lib/Sema/CSBindings.cpp

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@
2222
using namespace swift;
2323
using namespace constraints;
2424

25+
bool ConstraintSystem::PotentialBinding::isViableForJoin() const {
26+
return Kind == AllowedBindingKind::Supertypes &&
27+
!BindingType->hasLValueType() &&
28+
!BindingType->hasUnresolvedType() &&
29+
!BindingType->hasTypeVariable() &&
30+
!BindingType->hasHole() &&
31+
!BindingType->hasUnboundGenericType() &&
32+
!hasDefaultedLiteralProtocol() &&
33+
!isDefaultableBinding();
34+
}
35+
2536
bool ConstraintSystem::PotentialBindings::isPotentiallyIncomplete() const {
2637
// Generic parameters are always potentially incomplete.
2738
if (isGenericParameter())
@@ -679,30 +690,30 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
679690
// If this is a non-defaulted supertype binding,
680691
// check whether we can combine it with another
681692
// supertype binding by computing the 'join' of the types.
682-
if (binding.Kind == AllowedBindingKind::Supertypes &&
683-
!binding.BindingType->hasUnresolvedType() &&
684-
!binding.BindingType->hasTypeVariable() &&
685-
!binding.BindingType->hasHole() &&
686-
!binding.BindingType->hasUnboundGenericType() &&
687-
!binding.hasDefaultedLiteralProtocol() &&
688-
!binding.isDefaultableBinding() && allowJoinMeet) {
689-
if (lastSupertypeIndex) {
690-
auto &lastBinding = Bindings[*lastSupertypeIndex];
691-
auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
692-
auto bindingType = binding.BindingType->getWithoutSpecifierType();
693-
694-
auto join = Type::join(lastType, bindingType);
695-
if (join && !(*join)->isAny() &&
696-
(!(*join)->getOptionalObjectType()
697-
|| !(*join)->getOptionalObjectType()->isAny())) {
698-
// Replace the last supertype binding with the join. We're done.
699-
lastBinding.BindingType = *join;
700-
return;
693+
if (binding.isViableForJoin() && allowJoinMeet) {
694+
bool joined = false;
695+
696+
auto isAcceptableJoin = [](Type type) {
697+
return !type->isAny() && (!type->getOptionalObjectType() ||
698+
!type->getOptionalObjectType()->isAny());
699+
};
700+
701+
for (auto &existingBinding : Bindings) {
702+
if (!existingBinding.isViableForJoin())
703+
continue;
704+
705+
auto join = Type::join(existingBinding.BindingType, binding.BindingType);
706+
707+
if (join && isAcceptableJoin(*join)) {
708+
existingBinding.BindingType = *join;
709+
joined = true;
701710
}
702711
}
703712

704-
// Record this as the most recent supertype index.
705-
lastSupertypeIndex = Bindings.size();
713+
// If new binding has been joined with at least one of existing
714+
// bindings, there is no reason to include it into the set.
715+
if (joined)
716+
return;
706717
}
707718

708719
if (auto *literalProtocol = binding.getDefaultedLiteralProtocol())

0 commit comments

Comments
 (0)