Skip to content

Commit 715ef50

Browse files
committed
[CSBindings] Don't track ExpressibleByNilLiteral as a coverable protocol
Since `ExpressibleByNilLiteral` doesn't have a default type, there is no need to track it in the set of protocols that could produce defaultable bindings if not "covered" by existing bindings.
1 parent 6a66895 commit 715ef50

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,25 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
401401
// Key is a literal protocol requirement, Value indicates whether (first)
402402
// given protocol is a direct requirement, and (second) whether it has been
403403
// covered by an existing binding.
404+
bool canBeNil = false;
404405
llvm::SmallMapVector<ProtocolDecl *, std::pair<bool, bool>, 4>
405406
literalProtocols;
406407
for (auto *constraint : Protocols) {
407-
if (constraint->getKind() == ConstraintKind::LiteralConformsTo)
408-
literalProtocols.insert({constraint->getProtocol(),
409-
{isDirectRequirement(constraint), false}});
408+
if (constraint->getKind() != ConstraintKind::LiteralConformsTo)
409+
continue;
410+
411+
auto *protocol = constraint->getProtocol();
412+
413+
// No reason to add `ExpressibleByNilLiteral` into the set
414+
// because it doesn't have a default type.
415+
if (protocol->isSpecificProtocol(
416+
KnownProtocolKind::ExpressibleByNilLiteral)) {
417+
canBeNil = true;
418+
continue;
419+
}
420+
421+
literalProtocols.insert(
422+
{protocol, {isDirectRequirement(constraint), false}});
410423
}
411424

412425
for (auto &binding : Bindings) {
@@ -435,17 +448,18 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
435448
if (isCovered)
436449
continue;
437450

438-
// FIXME: This is a hack and it's incorrect because it depends
439-
// on ordering of the literal procotols e.g. if `ExpressibleByNilLiteral`
440-
// appears before e.g. `ExpressibleByIntegerLiteral` we'd drop
441-
// optionality although that would be incorrect.
442451
do {
443452
// If the type conforms to this protocol, we're covered.
444453
if (TypeChecker::conformsToProtocol(type, protocol, cs.DC)) {
445454
isCovered = true;
446455
break;
447456
}
448457

458+
// Can't unwrap optionals if there is `ExpressibleByNilLiteral`
459+
// conformance requirement placed on the type variable.
460+
if (canBeNil)
461+
break;
462+
449463
// If this literal protocol is not a direct requirement it
450464
// would be possible to change optionality while inferring
451465
// bindings for a supertype, so this hack doesn't apply.

0 commit comments

Comments
 (0)