@@ -43,7 +43,7 @@ BindingSet::BindingSet(ConstraintSystem &CS, TypeVariableType *TypeVar,
4343 : CS(CS), TypeVar(TypeVar), Info(info) {
4444
4545 for (const auto &binding : info.Bindings )
46- addBinding (binding, /* isTransitive= */ false );
46+ addBinding (binding);
4747
4848 for (auto *constraint : info.Constraints ) {
4949 switch (constraint->getKind ()) {
@@ -596,7 +596,7 @@ void BindingSet::inferTransitiveKeyPathBindings() {
596596
597597 // Copy the bindings over to the root.
598598 for (const auto &binding : bindings.Bindings )
599- addBinding (binding, /* isTransitive= */ true );
599+ addBinding (binding. asTransitiveFrom (contextualRootVar) );
600600
601601 // Make a note that the key path root is transitively adjacent
602602 // to contextual root type variable and all of its variables.
@@ -606,9 +606,9 @@ void BindingSet::inferTransitiveKeyPathBindings() {
606606 bindings.AdjacentVars .end ());
607607 }
608608 } else {
609- addBinding (
610- binding. withSameSource ( inferredRootTy, AllowedBindingKind::Exact),
611- /* isTransitive= */ true );
609+ auto newBinding = binding. withSameSource (
610+ inferredRootTy, AllowedBindingKind::Exact);
611+ addBinding (newBinding. asTransitiveFrom (keyPathTy) );
612612 }
613613 }
614614 }
@@ -679,8 +679,9 @@ void BindingSet::inferTransitiveSupertypeBindings() {
679679 if (ConstraintSystem::typeVarOccursInType (TypeVar, type))
680680 continue ;
681681
682- addBinding (binding.withSameSource (type, AllowedBindingKind::Supertypes),
683- /* isTransitive=*/ true );
682+ auto newBinding =
683+ binding.withSameSource (type, AllowedBindingKind::Supertypes);
684+ addBinding (newBinding.asTransitiveFrom (entry.first ));
684685 }
685686 }
686687}
@@ -713,8 +714,7 @@ void BindingSet::inferTransitiveUnresolvedMemberRefBindings() {
713714 continue ;
714715 }
715716
716- addBinding ({protocolTy, AllowedBindingKind::Exact, constraint},
717- /* isTransitive=*/ false );
717+ addBinding ({protocolTy, AllowedBindingKind::Exact, constraint});
718718 }
719719 }
720720 }
@@ -829,8 +829,8 @@ bool BindingSet::finalizeKeyPathBindings() {
829829 // better diagnostics.
830830 auto keyPathTy = getKeyPathType (ctx, *capability, rootTy,
831831 CS.getKeyPathValueType (keyPath));
832- updatedBindings.insert (
833- {keyPathTy, AllowedBindingKind::Exact, locator });
832+ updatedBindings.insert ({keyPathTy, AllowedBindingKind::Exact, locator,
833+ /* originator= */ nullptr });
834834 } else if (CS.shouldAttemptFixes ()) {
835835 auto fixedRootTy = CS.getFixedType (rootTy);
836836 // If key path is structurally correct and has a resolved root
@@ -889,11 +889,11 @@ void BindingSet::finalizeUnresolvedMemberChainResult() {
889889 }
890890}
891891
892- void BindingSet::addBinding (PotentialBinding binding, bool isTransitive ) {
892+ void BindingSet::addBinding (PotentialBinding binding) {
893893 if (Bindings.count (binding))
894894 return ;
895895
896- if (!isViable (binding, isTransitive ))
896+ if (!isViable (binding))
897897 return ;
898898
899899 SmallPtrSet<TypeVariableType *, 4 > referencedTypeVars;
@@ -957,14 +957,26 @@ void BindingSet::addBinding(PotentialBinding binding, bool isTransitive) {
957957 for (auto existingBinding = Bindings.begin ();
958958 existingBinding != Bindings.end ();) {
959959 if (existingBinding->isViableForJoin ()) {
960- auto join =
960+ auto joinType =
961961 Type::join (existingBinding->BindingType , binding.BindingType );
962962
963- if (join && isAcceptableJoin (*join )) {
963+ if (joinType && isAcceptableJoin (*joinType )) {
964964 // Result of the join has to use new binding because it refers
965965 // to the constraint that triggered the join that replaced the
966966 // existing binding.
967- joined.push_back (binding.withType (*join));
967+ //
968+ // For "join" to be transitive, both bindings have to be as
969+ // well, otherwise we consider it a refinement of a direct
970+ // binding.
971+ auto *origintor =
972+ binding.isTransitive () && existingBinding->isTransitive ()
973+ ? binding.Originator
974+ : nullptr ;
975+
976+ PotentialBinding join (*joinType, binding.Kind , binding.BindingSource ,
977+ origintor);
978+
979+ joined.push_back (join);
968980 // Remove existing binding from the set.
969981 // It has to be re-introduced later, since its type has been changed.
970982 existingBinding = Bindings.erase (existingBinding);
@@ -1448,15 +1460,15 @@ static bool hasConversions(Type type) {
14481460 type->is <BuiltinType>() || type->is <ArchetypeType>());
14491461}
14501462
1451- bool BindingSet::isViable (PotentialBinding &binding, bool isTransitive ) {
1463+ bool BindingSet::isViable (PotentialBinding &binding) {
14521464 // Prevent against checking against the same opened nominal type
14531465 // over and over again. Doing so means redundant work in the best
14541466 // case. In the worst case, we'll produce lots of duplicate solutions
14551467 // for this constraint system, which is problematic for overload
14561468 // resolution.
14571469 auto type = binding.BindingType ;
14581470
1459- if (isTransitive && !checkTypeOfBinding (TypeVar, type))
1471+ if (binding. isTransitive () && !checkTypeOfBinding (TypeVar, type))
14601472 return false ;
14611473
14621474 auto *NTD = type->getAnyNominal ();
0 commit comments