@@ -436,6 +436,8 @@ void BindingSet::finalize(
436
436
inferTransitiveProtocolRequirements (inferredBindings);
437
437
inferTransitiveBindings (inferredBindings);
438
438
439
+ determineLiteralCoverage ();
440
+
439
441
if (auto *locator = TypeVar->getImpl ().getLocator ()) {
440
442
if (locator->isLastElement <LocatorPathElt::MemberRefBase>()) {
441
443
// If this is a base of an unresolved member chain, as a last
@@ -546,43 +548,67 @@ void BindingSet::addBinding(PotentialBinding binding) {
546
548
return ;
547
549
}
548
550
549
- // Check whether the given binding covers any of the literal protocols
550
- // associated with this type variable.
551
- {
552
- bool allowsNil = canBeNil ();
551
+ for (auto *adjacentVar : referencedTypeVars)
552
+ AdjacentVars.insert (adjacentVar);
553
553
554
- for ( auto &literal : Literals) {
555
- auto *protocol = literal. first ;
554
+ ( void )Bindings. insert ( std::move (binding));
555
+ }
556
556
557
- // Skip conformance to `nil` protocol since it doesn't
558
- // have a default type and can't affect binding set.
559
- if (protocol->isSpecificProtocol (
560
- KnownProtocolKind::ExpressibleByNilLiteral))
561
- continue ;
557
+ void BindingSet::determineLiteralCoverage () {
558
+ if (Literals.empty ())
559
+ return ;
562
560
563
- auto &info = literal. second ;
561
+ SmallVector<PotentialBinding, 4 > adjustedBindings ;
564
562
565
- if (!info.viableAsBinding ())
566
- continue ;
563
+ bool allowsNil = canBeNil ();
567
564
568
- bool isCovered = false ;
569
- Type adjustedTy;
565
+ for (auto binding = Bindings.begin (); binding != Bindings.end ();) {
566
+ bool isCovered = false ;
567
+ Type adjustedTy;
570
568
571
- std::tie (isCovered, adjustedTy) =
572
- isLiteralCoveredBy (info, binding, allowsNil);
569
+ // Tracks the number of covered literal requirements,
570
+ // so checking could be stopped as soon as all of the
571
+ // requirements are satisfied.
572
+ unsigned numCoveredRequirements = 0 ;
573
+ for (auto &literalRequirement : Literals) {
574
+ auto &literalInfo = literalRequirement.second ;
573
575
574
- if (!isCovered)
576
+ if (!literalInfo.viableAsBinding ()) {
577
+ ++numCoveredRequirements;
575
578
continue ;
579
+ }
580
+
581
+ std::tie (isCovered, adjustedTy) =
582
+ literalInfo.isCoveredBy (*binding, CS.DC , allowsNil);
576
583
577
- binding = binding.withType (adjustedTy);
578
- info.setCoveredBy (binding.getSource ());
584
+ if (isCovered) {
585
+ literalInfo.setCoveredBy (binding->getSource ());
586
+ ++numCoveredRequirements;
587
+ break ;
588
+ }
579
589
}
580
- }
581
590
582
- for (auto *adjacentVar : referencedTypeVars)
583
- AdjacentVars.insert (adjacentVar);
591
+ // If the type has been adjusted, we need to re-insert
592
+ // the binding but skip all of the previous checks.
593
+ //
594
+ // It's okay to do this here since iteration stops after
595
+ // first covering binding has been found.
596
+ if (isCovered && adjustedTy) {
597
+ binding = Bindings.erase (binding);
598
+ adjustedBindings.push_back (binding->withType (adjustedTy));
599
+ continue ;
600
+ }
584
601
585
- (void )Bindings.insert (std::move (binding));
602
+ // If all of the literal requirements are now covered
603
+ // by existing bindings, there is nothing left to do.
604
+ if (numCoveredRequirements == Literals.size ())
605
+ break ;
606
+
607
+ ++binding;
608
+ }
609
+
610
+ for (auto &newBinding : adjustedBindings)
611
+ (void )Bindings.insert (std::move (newBinding));
586
612
}
587
613
588
614
void BindingSet::addLiteralRequirement (Constraint *constraint) {
@@ -637,36 +663,6 @@ void BindingSet::addLiteralRequirement(Constraint *constraint) {
637
663
LiteralRequirement literal (
638
664
constraint, TypeChecker::getDefaultType (protocol, CS.DC ), isDirect);
639
665
640
- if (literal.viableAsBinding ()) {
641
- bool allowsNil = canBeNil ();
642
-
643
- for (auto binding = Bindings.begin (); binding != Bindings.end ();
644
- ++binding) {
645
- bool isCovered = false ;
646
- Type adjustedTy;
647
-
648
- std::tie (isCovered, adjustedTy) =
649
- isLiteralCoveredBy (literal, *binding, allowsNil);
650
-
651
- // No luck here, let's try next literal requirement.
652
- if (!isCovered)
653
- continue ;
654
-
655
- // If the type has been adjusted, we need to re-insert
656
- // the binding but skip all of the previous checks.
657
- //
658
- // It's okay to do this here since iteration stops after
659
- // first covering binding has been found.
660
- if (adjustedTy) {
661
- Bindings.erase (binding);
662
- Bindings.insert (binding->withType (adjustedTy));
663
- }
664
-
665
- literal.setCoveredBy (binding->getSource ());
666
- break ;
667
- }
668
- }
669
-
670
666
Literals.insert ({protocol, std::move (literal)});
671
667
}
672
668
0 commit comments