31
31
32
32
using namespace swift ;
33
33
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
-
77
34
// / Common preconditions for Equatable and Hashable.
78
35
static bool canDeriveConformance (DeclContext *DC,
79
36
NominalTypeDecl *target,
@@ -86,55 +43,16 @@ static bool canDeriveConformance(DeclContext *DC,
86
43
}
87
44
88
45
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 ();
91
51
}
92
52
93
53
return false ;
94
54
}
95
55
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
-
138
56
static std::pair<BraceStmt *, bool >
139
57
deriveBodyEquatable_enum_uninhabited_eq (AbstractFunctionDecl *eqDecl, void *) {
140
58
auto parentDC = eqDecl->getDeclContext ();
@@ -565,7 +483,8 @@ void DerivedConformance::tryDiagnoseFailedEquatableDerivation(
565
483
DeclContext *DC, NominalTypeDecl *nominal) {
566
484
ASTContext &ctx = DC->getASTContext ();
567
485
auto *equatableProto = ctx.getProtocol (KnownProtocolKind::Equatable);
568
- diagnoseFailedDerivation (DC, nominal, equatableProto);
486
+ diagnoseAnyNonConformingMemberTypes (DC, nominal, equatableProto);
487
+ diagnoseIfSynthesisUnsupportedForDecl (nominal, equatableProto);
569
488
}
570
489
571
490
// / Returns a new \c CallExpr representing
@@ -1048,7 +967,8 @@ void DerivedConformance::tryDiagnoseFailedHashableDerivation(
1048
967
DeclContext *DC, NominalTypeDecl *nominal) {
1049
968
ASTContext &ctx = DC->getASTContext ();
1050
969
auto *hashableProto = ctx.getProtocol (KnownProtocolKind::Hashable);
1051
- diagnoseFailedDerivation (DC, nominal, hashableProto);
970
+ diagnoseAnyNonConformingMemberTypes (DC, nominal, hashableProto);
971
+ diagnoseIfSynthesisUnsupportedForDecl (nominal, hashableProto);
1052
972
}
1053
973
1054
974
ValueDecl *DerivedConformance::deriveHashable (ValueDecl *requirement) {
0 commit comments