@@ -27,6 +27,9 @@ using namespace swift;
2727using namespace constraints ;
2828using namespace inference ;
2929
30+ static llvm::Optional<Type> checkTypeOfBinding (TypeVariableType *typeVar,
31+ Type type);
32+
3033bool BindingSet::forClosureResult () const {
3134 return Info.TypeVar ->getImpl ().isClosureResultType ();
3235}
@@ -457,9 +460,37 @@ void BindingSet::inferTransitiveBindings(
457460 inferredRootTy = fnType->getParams ()[0 ].getParameterType ();
458461 }
459462
460- if (inferredRootTy && !inferredRootTy->isTypeVariableOrMember ())
461- addBinding (
462- binding.withSameSource (inferredRootTy, BindingKind::Exact));
463+ if (inferredRootTy) {
464+ // If contextual root is not yet resolved, let's try to see if
465+ // there are any bindings in its set. The bindings could be
466+ // transitively used because conversions between generic arguments
467+ // are not allowed.
468+ if (auto *contextualRootVar = inferredRootTy->getAs <TypeVariableType>()) {
469+ auto rootBindings = inferredBindings.find (contextualRootVar);
470+ if (rootBindings != inferredBindings.end ()) {
471+ auto &bindings = rootBindings->getSecond ();
472+
473+ // Don't infer if root is not yet fully resolved.
474+ if (bindings.isDelayed ())
475+ continue ;
476+
477+ // Copy the bindings over to the root.
478+ for (const auto &binding : bindings.Bindings )
479+ addBinding (binding, /* isTransitive=*/ true );
480+
481+ // Make a note that the key path root is transitively adjacent
482+ // to contextual root type variable and all of its variables.
483+ // This is important for ranking.
484+ AdjacentVars.insert (contextualRootVar);
485+ AdjacentVars.insert (bindings.AdjacentVars .begin (),
486+ bindings.AdjacentVars .end ());
487+ }
488+ } else {
489+ addBinding (
490+ binding.withSameSource (inferredRootTy, BindingKind::Exact),
491+ /* isTransitive=*/ true );
492+ }
493+ }
463494 }
464495 }
465496 }
@@ -526,7 +557,8 @@ void BindingSet::inferTransitiveBindings(
526557 if (ConstraintSystem::typeVarOccursInType (TypeVar, type))
527558 continue ;
528559
529- addBinding (binding.withSameSource (type, BindingKind::Supertypes));
560+ addBinding (binding.withSameSource (type, BindingKind::Supertypes),
561+ /* isTransitive=*/ true );
530562 }
531563 }
532564}
@@ -604,7 +636,8 @@ void BindingSet::finalize(
604636 continue ;
605637 }
606638
607- addBinding ({protocolTy, AllowedBindingKind::Exact, constraint});
639+ addBinding ({protocolTy, AllowedBindingKind::Exact, constraint},
640+ /* isTransitive=*/ false );
608641 }
609642 }
610643 }
@@ -713,11 +746,11 @@ void BindingSet::finalize(
713746 }
714747}
715748
716- void BindingSet::addBinding (PotentialBinding binding) {
749+ void BindingSet::addBinding (PotentialBinding binding, bool isTransitive ) {
717750 if (Bindings.count (binding))
718751 return ;
719752
720- if (!isViable (binding))
753+ if (!isViable (binding, isTransitive ))
721754 return ;
722755
723756 SmallPtrSet<TypeVariableType *, 4 > referencedTypeVars;
@@ -1138,14 +1171,17 @@ void PotentialBindings::addLiteral(Constraint *constraint) {
11381171 Literals.insert (constraint);
11391172}
11401173
1141- bool BindingSet::isViable (PotentialBinding &binding) {
1174+ bool BindingSet::isViable (PotentialBinding &binding, bool isTransitive ) {
11421175 // Prevent against checking against the same opened nominal type
11431176 // over and over again. Doing so means redundant work in the best
11441177 // case. In the worst case, we'll produce lots of duplicate solutions
11451178 // for this constraint system, which is problematic for overload
11461179 // resolution.
11471180 auto type = binding.BindingType ;
11481181
1182+ if (isTransitive && !checkTypeOfBinding (TypeVar, type))
1183+ return false ;
1184+
11491185 auto *NTD = type->getAnyNominal ();
11501186 if (!NTD)
11511187 return true ;
0 commit comments