@@ -319,7 +319,7 @@ void ConstraintSystem::PotentialBindings::inferTransitiveBindings(
319
319
// `ExpressibleByStringLiteral` conformance, we'd end up picking
320
320
// `T` with only one type `Any?` which is incorrect.
321
321
for (const auto &literal : bindings.Literals )
322
- addLiteral (std::get< 0 >( literal.second ));
322
+ addLiteral (literal.second . getSource ( ));
323
323
324
324
// Infer transitive defaults.
325
325
for (const auto &def : bindings.Defaults )
@@ -476,7 +476,8 @@ void ConstraintSystem::PotentialBindings::addDefault(Constraint *constraint) {
476
476
Defaults.insert ({defaultTy->getCanonicalType (), constraint});
477
477
}
478
478
479
- static bool isCoveredBy (ProtocolDecl *protocol, Type type, DeclContext *useDC) {
479
+ bool ConstraintSystem::LiteralRequirement::isCoveredBy (
480
+ Type type, DeclContext *useDC) const {
480
481
auto coversDefaultType = [](Type type, Type defaultType) -> bool {
481
482
if (!defaultType->hasUnboundGenericType ())
482
483
return type->isEqual (defaultType);
@@ -493,17 +494,15 @@ static bool isCoveredBy(ProtocolDecl *protocol, Type type, DeclContext *useDC) {
493
494
return nominal == type->getAnyNominal ();
494
495
};
495
496
496
- if (auto defaultType = TypeChecker::getDefaultType (protocol, useDC)) {
497
- if (coversDefaultType (type, defaultType))
498
- return true ;
499
- }
497
+ if (hasDefaultType () && coversDefaultType (type, getDefaultType ()))
498
+ return true ;
500
499
501
- return bool (TypeChecker::conformsToProtocol (type, protocol , useDC));
500
+ return bool (TypeChecker::conformsToProtocol (type, getProtocol () , useDC));
502
501
}
503
502
504
503
bool ConstraintSystem::PotentialBindings::isLiteralCoveredBy (
505
- ProtocolDecl * literal, PotentialBinding &binding, bool canBeNil ,
506
- bool isDirectRequirement ) const {
504
+ const LiteralRequirement & literal, PotentialBinding &binding,
505
+ bool canBeNil ) const {
507
506
auto type = binding.BindingType ;
508
507
switch (binding.Kind ) {
509
508
case AllowedBindingKind::Exact:
@@ -521,7 +520,7 @@ bool ConstraintSystem::PotentialBindings::isLiteralCoveredBy(
521
520
522
521
bool requiresUnwrap = false ;
523
522
do {
524
- if (isCoveredBy (literal, type, CS.DC )) {
523
+ if (literal. isCoveredBy (type, CS.DC )) {
525
524
// FIXME: Side-effect like this is not great (to say the least),
526
525
// but this is an artifact of the binding collection which could
527
526
// be fixed separately.
@@ -538,7 +537,7 @@ bool ConstraintSystem::PotentialBindings::isLiteralCoveredBy(
538
537
// If this literal protocol is not a direct requirement it
539
538
// would not be possible to change optionality while inferring
540
539
// bindings for a supertype, so this hack doesn't apply.
541
- if (!isDirectRequirement)
540
+ if (!literal. isDirectRequirement () )
542
541
return false ;
543
542
544
543
// If we're allowed to bind to subtypes, look through optionals.
@@ -613,12 +612,11 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
613
612
KnownProtocolKind::ExpressibleByNilLiteral))
614
613
continue ;
615
614
616
- auto isDirectRequirement = std::get<1 >(literal.second );
617
- auto *&coveredBy = std::get<2 >(literal.second );
615
+ auto &info = literal.second ;
618
616
619
- if (!coveredBy &&
620
- isLiteralCoveredBy (protocol , binding, allowsNil, isDirectRequirement ))
621
- coveredBy = binding.getSource ();
617
+ if (info. viableAsBinding () &&
618
+ isLiteralCoveredBy (info , binding, allowsNil))
619
+ info. setCoveredBy ( binding.getSource () );
622
620
}
623
621
}
624
622
@@ -661,32 +659,38 @@ void ConstraintSystem::PotentialBindings::addLiteral(Constraint *constraint) {
661
659
return ;
662
660
663
661
bool isDirect = isDirectRequirement (constraint);
664
- Constraint *coveredBy = nullptr ;
665
662
666
663
// Coverage is not applicable to `ExpressibleByNilLiteral` since it
667
664
// doesn't have a default type.
668
665
if (protocol->isSpecificProtocol (
669
666
KnownProtocolKind::ExpressibleByNilLiteral)) {
670
- Literals.insert (
671
- {protocol, std::make_tuple (constraint, isDirect, coveredBy)});
667
+ Literals.insert ({protocol,
668
+ {.Source = constraint,
669
+ .DefaultType = Type (),
670
+ .IsDirectRequirement = isDirect}});
672
671
return ;
673
672
}
674
673
675
674
// Check whether any of the existing bindings covers this literal
676
675
// protocol.
676
+ LiteralRequirement literal{.Source = constraint,
677
+ .DefaultType =
678
+ TypeChecker::getDefaultType (protocol, CS.DC ),
679
+ .IsDirectRequirement = isDirect};
680
+
677
681
{
678
682
bool allowsNil = canBeNil ();
679
683
680
684
for (auto &binding : Bindings) {
681
- if (!coveredBy &&
682
- isLiteralCoveredBy (protocol , binding, allowsNil, isDirect )) {
683
- coveredBy = binding.getSource ();
685
+ if (!literal. isCovered () &&
686
+ isLiteralCoveredBy (literal , binding, allowsNil)) {
687
+ literal. setCoveredBy ( binding.getSource () );
684
688
break ;
685
689
}
686
690
}
687
691
}
688
692
689
- Literals.insert ({protocol, std::make_tuple (constraint, isDirect, coveredBy )});
693
+ Literals.insert ({protocol, std::move (literal )});
690
694
}
691
695
692
696
bool ConstraintSystem::PotentialBindings::isViable (
@@ -1180,10 +1184,10 @@ ConstraintSystem::PotentialBindings::getLiteralKind() const {
1180
1184
1181
1185
for (const auto &literal : Literals) {
1182
1186
auto *protocol = literal.first ;
1183
- auto *coveredBy = std::get< 2 >( literal.second ) ;
1187
+ const auto &info = literal.second ;
1184
1188
1185
1189
// Only uncovered defaultable literal protocols participate.
1186
- if (coveredBy || ! TypeChecker::getDefaultType (protocol, CS. DC ))
1190
+ if (!info. viableAsBinding ( ))
1187
1191
continue ;
1188
1192
1189
1193
switch (*protocol->getKnownProtocolKind ()) {
@@ -1210,8 +1214,7 @@ ConstraintSystem::PotentialBindings::getLiteralKind() const {
1210
1214
unsigned
1211
1215
ConstraintSystem::PotentialBindings::getNumViableLiteralBindings () const {
1212
1216
return llvm::count_if (Literals, [&](const auto &literal) {
1213
- auto *coveredBy = std::get<2 >(literal.second );
1214
- return !(coveredBy || !TypeChecker::getDefaultType (literal.first , CS.DC ));
1217
+ return literal.second .viableAsBinding ();
1215
1218
});
1216
1219
}
1217
1220
0 commit comments