@@ -401,12 +401,45 @@ 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+ // Let's try to coalesce integer and floating point literal protocols
422+ // if they appear together because the only possible default type that
423+ // could satisfy both requirements is `Double`.
424+ {
425+ if (protocol->isSpecificProtocol (
426+ KnownProtocolKind::ExpressibleByIntegerLiteral)) {
427+ auto *floatLiteral = CS.getASTContext ().getProtocol (
428+ KnownProtocolKind::ExpressibleByFloatLiteral);
429+ if (literalProtocols.count (floatLiteral))
430+ continue ;
431+ }
432+
433+ if (protocol->isSpecificProtocol (
434+ KnownProtocolKind::ExpressibleByFloatLiteral)) {
435+ auto *intLiteral = CS.getASTContext ().getProtocol (
436+ KnownProtocolKind::ExpressibleByIntegerLiteral);
437+ literalProtocols.erase (intLiteral);
438+ }
439+ }
440+
441+ literalProtocols.insert (
442+ {protocol, {isDirectRequirement (constraint), false }});
410443 }
411444
412445 for (auto &binding : Bindings) {
@@ -435,19 +468,20 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
435468 if (isCovered)
436469 continue ;
437470
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.
442471 do {
443472 // If the type conforms to this protocol, we're covered.
444473 if (TypeChecker::conformsToProtocol (type, protocol, cs.DC )) {
445474 isCovered = true ;
446475 break ;
447476 }
448477
478+ // Can't unwrap optionals if there is `ExpressibleByNilLiteral`
479+ // conformance requirement placed on the type variable.
480+ if (canBeNil)
481+ break ;
482+
449483 // If this literal protocol is not a direct requirement it
450- // would be possible to change optionality while inferring
484+ // would not be possible to change optionality while inferring
451485 // bindings for a supertype, so this hack doesn't apply.
452486 if (!isDirectRequirement)
453487 break ;
@@ -472,31 +506,23 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
472506 binding.BindingType = type;
473507 }
474508
475- // If this is not a literal protocol or it has been "covered" by an existing
476- // binding it can't provide a default type.
477- auto isUnviableForDefaulting = [&literalProtocols](ProtocolDecl *protocol) {
478- auto literal = literalProtocols.find (protocol);
479- return literal == literalProtocols.end () || literal->second .second ;
480- };
481-
482509 for (auto *constraint : Protocols) {
483510 auto *protocol = constraint->getProtocol ();
484511
485- if (isUnviableForDefaulting (protocol))
512+ auto literal = literalProtocols.find (protocol);
513+ if (literal == literalProtocols.end ())
486514 continue ;
487515
488- // Let's try to coalesce integer and floating point literal protocols
489- // if they appear together because the only possible default type that
490- // could satisfy both requirements is `Double`.
491- if (protocol->isSpecificProtocol (
492- KnownProtocolKind::ExpressibleByIntegerLiteral)) {
493- auto *floatLiteral = cs.getASTContext ().getProtocol (
494- KnownProtocolKind::ExpressibleByFloatLiteral);
495- // If `ExpressibleByFloatLiteral` is a requirement and it isn't
496- // covered, let's skip `ExpressibleByIntegerLiteral` requirement.
497- if (!isUnviableForDefaulting (floatLiteral))
498- continue ;
499- }
516+ bool isDirectRequirement = false ;
517+ bool isCovered = false ;
518+
519+ std::tie (isDirectRequirement, isCovered) = literal->second ;
520+
521+ // Can't be defaulted because it's already covered by an
522+ // existing direct or transitive binding which is always
523+ // better.
524+ if (isCovered)
525+ continue ;
500526
501527 auto defaultType = TypeChecker::getDefaultType (protocol, cs.DC );
502528 if (!defaultType)
@@ -509,9 +535,8 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
509535 // requirement or inferred transitive one to identify binding
510536 // kind correctly.
511537 addPotentialBinding ({defaultType,
512- isDirectRequirement (constraint)
513- ? AllowedBindingKind::Subtypes
514- : AllowedBindingKind::Supertypes,
538+ isDirectRequirement ? AllowedBindingKind::Subtypes
539+ : AllowedBindingKind::Supertypes,
515540 constraint});
516541 }
517542}
0 commit comments