@@ -5551,23 +5551,24 @@ void swift::diagnoseConformanceFailure(Type T,
5551
5551
5552
5552
// If we're checking conformance of an existential type to a protocol,
5553
5553
// 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,
5562
5569
T, Proto->getDeclaredInterfaceType ());
5563
- diags.diagnose (ComplainLoc,
5564
- diag::only_concrete_types_conform_to_protocols);
5565
5570
return ;
5566
5571
}
5567
-
5568
- diags.diagnose (ComplainLoc, diag::protocol_does_not_conform_static,
5569
- T, Proto->getDeclaredInterfaceType ());
5570
- return ;
5571
5572
}
5572
5573
5573
5574
// Special case: diagnose conversion to ExpressibleByNilLiteral, since we
@@ -5685,7 +5686,7 @@ void swift::diagnoseConformanceFailure(Type T,
5685
5686
T, Proto->getDeclaredInterfaceType ());
5686
5687
}
5687
5688
5688
- ProtocolConformanceRef
5689
+ std::pair< bool , ProtocolConformanceRef>
5689
5690
TypeChecker::containsProtocol (Type T, ProtocolDecl *Proto,
5690
5691
bool allowMissing) {
5691
5692
// Existential types don't need to conform, i.e., they only need to
@@ -5699,7 +5700,8 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto,
5699
5700
if (constraint->isEqual (Proto->getDeclaredInterfaceType ()) &&
5700
5701
Proto->requiresSelfConformanceWitnessTable ()) {
5701
5702
auto &ctx = T->getASTContext ();
5702
- return ProtocolConformanceRef (ctx.getSelfConformance (Proto));
5703
+ auto conformance = ProtocolConformanceRef (ctx.getSelfConformance (Proto));
5704
+ return std::make_pair (false , conformance);
5703
5705
}
5704
5706
5705
5707
auto layout = T->getExistentialLayout ();
@@ -5711,35 +5713,28 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto,
5711
5713
// would result in a missing conformance if type is `& Sendable`
5712
5714
// protocol composition. It's handled for type as a whole below.
5713
5715
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);
5719
5720
}
5720
5721
5721
5722
// Next, check if the existential contains the protocol in question.
5722
5723
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 ());
5735
5727
}
5736
5728
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);
5739
5733
}
5740
5734
5741
5735
// 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);
5743
5738
}
5744
5739
5745
5740
bool TypeChecker::conformsToKnownProtocol (
0 commit comments