@@ -53,7 +53,7 @@ BindingSet::BindingSet(ConstraintSystem &CS, TypeVariableType *TypeVar,
5353 : CS(CS), TypeVar(TypeVar), Info(info) {
5454
5555 for (const auto &binding : info.Bindings )
56- addBinding (binding, /* isTransitive= */ false );
56+ addBinding (binding);
5757
5858 for (const auto &literal : info.Literals )
5959 Literals.push_back (literal);
@@ -594,7 +594,7 @@ void BindingSet::inferTransitiveKeyPathBindings() {
594594
595595 // Copy the bindings over to the root.
596596 for (const auto &binding : bindings.Bindings )
597- addBinding (binding, /* isTransitive= */ true );
597+ addBinding (binding. asTransitiveFrom (contextualRootVar) );
598598
599599 // Make a note that the key path root is transitively adjacent
600600 // to contextual root type variable and all of its variables.
@@ -604,9 +604,9 @@ void BindingSet::inferTransitiveKeyPathBindings() {
604604 bindings.AdjacentVars .end ());
605605 }
606606 } else {
607- addBinding (
608- binding. withSameSource ( inferredRootTy, AllowedBindingKind::Exact),
609- /* isTransitive= */ true );
607+ auto newBinding = binding. withSameSource (
608+ inferredRootTy, AllowedBindingKind::Exact);
609+ addBinding (newBinding. asTransitiveFrom (keyPathTy) );
610610 }
611611 }
612612 }
@@ -699,8 +699,9 @@ void BindingSet::inferTransitiveSupertypeBindings() {
699699 if (ConstraintSystem::typeVarOccursInType (TypeVar, type))
700700 continue ;
701701
702- addBinding (binding.withSameSource (type, AllowedBindingKind::Supertypes),
703- /* isTransitive=*/ true );
702+ auto newBinding =
703+ binding.withSameSource (type, AllowedBindingKind::Supertypes);
704+ addBinding (newBinding.asTransitiveFrom (entry.first ));
704705 }
705706 }
706707}
@@ -733,8 +734,7 @@ void BindingSet::inferTransitiveUnresolvedMemberRefBindings() {
733734 continue ;
734735 }
735736
736- addBinding ({protocolTy, AllowedBindingKind::Exact, constraint},
737- /* isTransitive=*/ false );
737+ addBinding ({protocolTy, AllowedBindingKind::Exact, constraint});
738738 }
739739 }
740740 }
@@ -849,8 +849,8 @@ bool BindingSet::finalizeKeyPathBindings() {
849849 // better diagnostics.
850850 auto keyPathTy = getKeyPathType (ctx, *capability, rootTy,
851851 CS.getKeyPathValueType (keyPath));
852- updatedBindings.insert (
853- {keyPathTy, AllowedBindingKind::Exact, locator });
852+ updatedBindings.insert ({keyPathTy, AllowedBindingKind::Exact, locator,
853+ /* originator= */ nullptr });
854854 } else if (CS.shouldAttemptFixes ()) {
855855 auto fixedRootTy = CS.getFixedType (rootTy);
856856 // If key path is structurally correct and has a resolved root
@@ -911,11 +911,11 @@ void BindingSet::finalizeUnresolvedMemberChainResult() {
911911 }
912912}
913913
914- void BindingSet::addBinding (PotentialBinding binding, bool isTransitive ) {
914+ void BindingSet::addBinding (PotentialBinding binding) {
915915 if (Bindings.count (binding))
916916 return ;
917917
918- if (!isViable (binding, isTransitive ))
918+ if (!isViable (binding))
919919 return ;
920920
921921 SmallPtrSet<TypeVariableType *, 4 > referencedTypeVars;
@@ -979,14 +979,26 @@ void BindingSet::addBinding(PotentialBinding binding, bool isTransitive) {
979979 for (auto existingBinding = Bindings.begin ();
980980 existingBinding != Bindings.end ();) {
981981 if (existingBinding->isViableForJoin ()) {
982- auto join =
982+ auto joinType =
983983 Type::join (existingBinding->BindingType , binding.BindingType );
984984
985- if (join && isAcceptableJoin (*join )) {
985+ if (joinType && isAcceptableJoin (*joinType )) {
986986 // Result of the join has to use new binding because it refers
987987 // to the constraint that triggered the join that replaced the
988988 // existing binding.
989- joined.push_back (binding.withType (*join));
989+ //
990+ // For "join" to be transitive, both bindings have to be as
991+ // well, otherwise we consider it a refinement of a direct
992+ // binding.
993+ auto *origintor =
994+ binding.isTransitive () && existingBinding->isTransitive ()
995+ ? binding.Originator
996+ : nullptr ;
997+
998+ PotentialBinding join (*joinType, binding.Kind , binding.BindingSource ,
999+ origintor);
1000+
1001+ joined.push_back (join);
9901002 // Remove existing binding from the set.
9911003 // It has to be re-introduced later, since its type has been changed.
9921004 existingBinding = Bindings.erase (existingBinding);
@@ -1469,15 +1481,15 @@ static bool hasConversions(Type type) {
14691481 type->is <BuiltinType>() || type->is <ArchetypeType>());
14701482}
14711483
1472- bool BindingSet::isViable (PotentialBinding &binding, bool isTransitive ) {
1484+ bool BindingSet::isViable (PotentialBinding &binding) {
14731485 // Prevent against checking against the same opened nominal type
14741486 // over and over again. Doing so means redundant work in the best
14751487 // case. In the worst case, we'll produce lots of duplicate solutions
14761488 // for this constraint system, which is problematic for overload
14771489 // resolution.
14781490 auto type = binding.BindingType ;
14791491
1480- if (isTransitive && !checkTypeOfBinding (TypeVar, type))
1492+ if (binding. isTransitive () && !checkTypeOfBinding (TypeVar, type))
14811493 return false ;
14821494
14831495 auto *NTD = type->getAnyNominal ();
0 commit comments