@@ -27,6 +27,9 @@ using namespace swift;
27
27
using namespace constraints ;
28
28
using namespace inference ;
29
29
30
+ static llvm::Optional<Type> checkTypeOfBinding (TypeVariableType *typeVar,
31
+ Type type);
32
+
30
33
bool BindingSet::forClosureResult () const {
31
34
return Info.TypeVar ->getImpl ().isClosureResultType ();
32
35
}
@@ -457,9 +460,37 @@ void BindingSet::inferTransitiveBindings(
457
460
inferredRootTy = fnType->getParams ()[0 ].getParameterType ();
458
461
}
459
462
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
+ }
463
494
}
464
495
}
465
496
}
@@ -526,7 +557,8 @@ void BindingSet::inferTransitiveBindings(
526
557
if (ConstraintSystem::typeVarOccursInType (TypeVar, type))
527
558
continue ;
528
559
529
- addBinding (binding.withSameSource (type, BindingKind::Supertypes));
560
+ addBinding (binding.withSameSource (type, BindingKind::Supertypes),
561
+ /* isTransitive=*/ true );
530
562
}
531
563
}
532
564
}
@@ -604,7 +636,8 @@ void BindingSet::finalize(
604
636
continue ;
605
637
}
606
638
607
- addBinding ({protocolTy, AllowedBindingKind::Exact, constraint});
639
+ addBinding ({protocolTy, AllowedBindingKind::Exact, constraint},
640
+ /* isTransitive=*/ false );
608
641
}
609
642
}
610
643
}
@@ -713,11 +746,11 @@ void BindingSet::finalize(
713
746
}
714
747
}
715
748
716
- void BindingSet::addBinding (PotentialBinding binding) {
749
+ void BindingSet::addBinding (PotentialBinding binding, bool isTransitive ) {
717
750
if (Bindings.count (binding))
718
751
return ;
719
752
720
- if (!isViable (binding))
753
+ if (!isViable (binding, isTransitive ))
721
754
return ;
722
755
723
756
SmallPtrSet<TypeVariableType *, 4 > referencedTypeVars;
@@ -1138,14 +1171,17 @@ void PotentialBindings::addLiteral(Constraint *constraint) {
1138
1171
Literals.insert (constraint);
1139
1172
}
1140
1173
1141
- bool BindingSet::isViable (PotentialBinding &binding) {
1174
+ bool BindingSet::isViable (PotentialBinding &binding, bool isTransitive ) {
1142
1175
// Prevent against checking against the same opened nominal type
1143
1176
// over and over again. Doing so means redundant work in the best
1144
1177
// case. In the worst case, we'll produce lots of duplicate solutions
1145
1178
// for this constraint system, which is problematic for overload
1146
1179
// resolution.
1147
1180
auto type = binding.BindingType ;
1148
1181
1182
+ if (isTransitive && !checkTypeOfBinding (TypeVar, type))
1183
+ return false ;
1184
+
1149
1185
auto *NTD = type->getAnyNominal ();
1150
1186
if (!NTD)
1151
1187
return true ;
0 commit comments