@@ -5551,23 +5551,24 @@ void swift::diagnoseConformanceFailure(Type T,
55515551
55525552 // If we're checking conformance of an existential type to a protocol,
55535553 // do a little bit of extra work to produce a better diagnostic.
5554- if (T->isExistentialType () &&
5555- TypeChecker::containsProtocol (T, Proto)) {
5556-
5557- if (!T->isObjCExistentialType ()) {
5558- Type constraintType = T;
5559- if (auto existential = T->getAs <ExistentialType>())
5560- constraintType = existential->getConstraintType ();
5561- diags.diagnose (ComplainLoc, diag::type_cannot_conform,
5554+ if (T->isExistentialType ()) {
5555+ auto pair = TypeChecker::containsProtocol (T, Proto);
5556+ if (pair.first || pair.second ) {
5557+ if (!T->isObjCExistentialType ()) {
5558+ Type constraintType = T;
5559+ if (auto existential = T->getAs <ExistentialType>())
5560+ constraintType = existential->getConstraintType ();
5561+ diags.diagnose (ComplainLoc, diag::type_cannot_conform,
5562+ T, Proto->getDeclaredInterfaceType ());
5563+ diags.diagnose (ComplainLoc,
5564+ diag::only_concrete_types_conform_to_protocols);
5565+ return ;
5566+ }
5567+
5568+ diags.diagnose (ComplainLoc, diag::protocol_does_not_conform_static,
55625569 T, Proto->getDeclaredInterfaceType ());
5563- diags.diagnose (ComplainLoc,
5564- diag::only_concrete_types_conform_to_protocols);
55655570 return ;
55665571 }
5567-
5568- diags.diagnose (ComplainLoc, diag::protocol_does_not_conform_static,
5569- T, Proto->getDeclaredInterfaceType ());
5570- return ;
55715572 }
55725573
55735574 // Special case: diagnose conversion to ExpressibleByNilLiteral, since we
@@ -5685,7 +5686,7 @@ void swift::diagnoseConformanceFailure(Type T,
56855686 T, Proto->getDeclaredInterfaceType ());
56865687}
56875688
5688- ProtocolConformanceRef
5689+ std::pair< bool , ProtocolConformanceRef>
56895690TypeChecker::containsProtocol (Type T, ProtocolDecl *Proto,
56905691 bool allowMissing) {
56915692 // Existential types don't need to conform, i.e., they only need to
@@ -5699,7 +5700,8 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto,
56995700 if (constraint->isEqual (Proto->getDeclaredInterfaceType ()) &&
57005701 Proto->requiresSelfConformanceWitnessTable ()) {
57015702 auto &ctx = T->getASTContext ();
5702- return ProtocolConformanceRef (ctx.getSelfConformance (Proto));
5703+ auto conformance = ProtocolConformanceRef (ctx.getSelfConformance (Proto));
5704+ return std::make_pair (false , conformance);
57035705 }
57045706
57055707 auto layout = T->getExistentialLayout ();
@@ -5711,35 +5713,28 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto,
57115713 // would result in a missing conformance if type is `& Sendable`
57125714 // protocol composition. It's handled for type as a whole below.
57135715 if (auto superclass = layout.getSuperclass ()) {
5714- auto result =lookupConformance (superclass, Proto,
5715- /* allowMissing=*/ false );
5716- if (result) {
5717- return result;
5718- }
5716+ auto conformance = lookupConformance (superclass, Proto,
5717+ /* allowMissing=*/ false );
5718+ if (conformance)
5719+ return std::make_pair (false , conformance);
57195720 }
57205721
57215722 // Next, check if the existential contains the protocol in question.
57225723 for (auto *PD : layout.getProtocols ()) {
5723- // If we found the protocol we're looking for, return an abstract
5724- // conformance to it.
5725- if (PD == Proto) {
5726- // FIXME: Passing an empty Type() here temporarily.
5727- return ProtocolConformanceRef::forAbstract (Type (), Proto);
5728- }
5729-
5730- // Now check refined protocols.
5731- if (PD->inheritsFrom (Proto)) {
5732- // FIXME: Passing an empty Type() here temporarily.
5733- return ProtocolConformanceRef::forAbstract (Type (), Proto);
5734- }
5724+ // If we found the protocol we're looking for, return the special value.
5725+ if (PD == Proto || PD->inheritsFrom (Proto))
5726+ return std::make_pair (true , ProtocolConformanceRef::forInvalid ());
57355727 }
57365728
5737- return allowMissing ? ProtocolConformanceRef::forMissingOrInvalid (T, Proto)
5738- : ProtocolConformanceRef::forInvalid ();
5729+ auto conformance =
5730+ (allowMissing ? ProtocolConformanceRef::forMissingOrInvalid (T, Proto)
5731+ : ProtocolConformanceRef::forInvalid ());
5732+ return std::make_pair (false , conformance);
57395733 }
57405734
57415735 // For non-existential types, this is equivalent to checking conformance.
5742- return lookupConformance (T, Proto, allowMissing);
5736+ auto conformance = lookupConformance (T, Proto, allowMissing);
5737+ return std::make_pair (false , conformance);
57435738}
57445739
57455740bool TypeChecker::conformsToKnownProtocol (
0 commit comments