3131
3232using namespace swift ;
3333
34- enum NonconformingMemberKind {
35- AssociatedValue,
36- StoredProperty
37- };
38-
39- // / Returns the VarDecl of each stored property in the given struct whose type
40- // / does not conform to a protocol.
41- // / \p theStruct The struct whose stored properties should be checked.
42- // / \p protocol The protocol being requested.
43- // / \return The VarDecl of each stored property whose type does not conform.
44- static SmallVector<VarDecl *, 3 >
45- storedPropertiesNotConformingToProtocol (DeclContext *DC, StructDecl *theStruct,
46- ProtocolDecl *protocol) {
47- auto storedProperties = theStruct->getStoredProperties ();
48- SmallVector<VarDecl *, 3 > nonconformingProperties;
49- for (auto propertyDecl : storedProperties) {
50- if (!propertyDecl->isUserAccessible ())
51- continue ;
52-
53- auto type = propertyDecl->getValueInterfaceType ();
54- if (!type)
55- nonconformingProperties.push_back (propertyDecl);
56-
57- if (!TypeChecker::conformsToProtocol (DC->mapTypeIntoContext (type), protocol,
58- DC)) {
59- nonconformingProperties.push_back (propertyDecl);
60- }
61- }
62- return nonconformingProperties;
63- }
64-
65- // / Returns true if every stored property in the given struct conforms to the
66- // / protocol (or, vacuously, if it has no stored properties).
67- // / \p theStruct The struct whose stored properties should be checked.
68- // / \p protocol The protocol being requested.
69- // / \return True if all stored properties of the struct conform.
70- static bool allStoredPropertiesConformToProtocol (DeclContext *DC,
71- StructDecl *theStruct,
72- ProtocolDecl *protocol) {
73- return storedPropertiesNotConformingToProtocol (DC, theStruct, protocol)
74- .empty ();
75- }
76-
7734// / Common preconditions for Equatable and Hashable.
7835static bool canDeriveConformance (DeclContext *DC,
7936 NominalTypeDecl *target,
@@ -86,55 +43,16 @@ static bool canDeriveConformance(DeclContext *DC,
8643 }
8744
8845 if (auto structDecl = dyn_cast<StructDecl>(target)) {
89- // All stored properties of the struct must conform to the protocol.
90- return allStoredPropertiesConformToProtocol (DC, structDecl, protocol);
46+ // All stored properties of the struct must conform to the protocol. If
47+ // there are no stored properties, we will vaccously return true.
48+ return DerivedConformance::storedPropertiesNotConformingToProtocol (
49+ DC, structDecl, protocol)
50+ .empty ();
9151 }
9252
9353 return false ;
9454}
9555
96- // / Diagnose failed conformance synthesis caused by a member type not conforming
97- // / to the same protocol
98- void diagnoseFailedDerivation (DeclContext *DC, NominalTypeDecl *nominal,
99- ProtocolDecl *protocol) {
100- ASTContext &ctx = DC->getASTContext ();
101-
102- if (auto *enumDecl = dyn_cast<EnumDecl>(nominal)) {
103- auto nonconformingAssociatedTypes =
104- DerivedConformance::associatedValuesNotConformingToProtocol (DC, enumDecl, protocol);
105- for (auto *typeToDiagnose : nonconformingAssociatedTypes) {
106- SourceLoc reprLoc;
107- if (auto *repr = typeToDiagnose->getTypeRepr ())
108- reprLoc = repr->getStartLoc ();
109- ctx.Diags .diagnose (
110- reprLoc,
111- diag::missing_member_type_conformance_prevents_synthesis,
112- NonconformingMemberKind::AssociatedValue,
113- typeToDiagnose->getInterfaceType (), protocol->getDeclaredType (),
114- nominal->getDeclaredInterfaceType ());
115- }
116- }
117-
118- if (auto *structDecl = dyn_cast<StructDecl>(nominal)) {
119- auto nonconformingStoredProperties =
120- storedPropertiesNotConformingToProtocol (DC, structDecl, protocol);
121- for (auto *propertyToDiagnose : nonconformingStoredProperties) {
122- ctx.Diags .diagnose (
123- propertyToDiagnose->getLoc (),
124- diag::missing_member_type_conformance_prevents_synthesis,
125- NonconformingMemberKind::StoredProperty,
126- propertyToDiagnose->getInterfaceType (), protocol->getDeclaredType (),
127- nominal->getDeclaredInterfaceType ());
128- }
129- }
130-
131- if (auto *classDecl = dyn_cast<ClassDecl>(nominal)) {
132- ctx.Diags .diagnose (classDecl->getLoc (),
133- diag::automatic_protocol_synthesis_unsupported,
134- protocol->getName ().str (), 0 );
135- }
136- }
137-
13856static std::pair<BraceStmt *, bool >
13957deriveBodyEquatable_enum_uninhabited_eq (AbstractFunctionDecl *eqDecl, void *) {
14058 auto parentDC = eqDecl->getDeclContext ();
@@ -565,7 +483,8 @@ void DerivedConformance::tryDiagnoseFailedEquatableDerivation(
565483 DeclContext *DC, NominalTypeDecl *nominal) {
566484 ASTContext &ctx = DC->getASTContext ();
567485 auto *equatableProto = ctx.getProtocol (KnownProtocolKind::Equatable);
568- diagnoseFailedDerivation (DC, nominal, equatableProto);
486+ diagnoseAnyNonConformingMemberTypes (DC, nominal, equatableProto);
487+ diagnoseIfSynthesisUnsupportedForDecl (nominal, equatableProto);
569488}
570489
571490// / Returns a new \c CallExpr representing
@@ -1048,7 +967,8 @@ void DerivedConformance::tryDiagnoseFailedHashableDerivation(
1048967 DeclContext *DC, NominalTypeDecl *nominal) {
1049968 ASTContext &ctx = DC->getASTContext ();
1050969 auto *hashableProto = ctx.getProtocol (KnownProtocolKind::Hashable);
1051- diagnoseFailedDerivation (DC, nominal, hashableProto);
970+ diagnoseAnyNonConformingMemberTypes (DC, nominal, hashableProto);
971+ diagnoseIfSynthesisUnsupportedForDecl (nominal, hashableProto);
1052972}
1053973
1054974ValueDecl *DerivedConformance::deriveHashable (ValueDecl *requirement) {
0 commit comments