22
22
#include " DerivedConformances.h"
23
23
24
24
using namespace swift ;
25
- using namespace DerivedConformance ;
26
25
27
26
// / Common preconditions for CaseIterable.
28
27
static bool canDeriveConformance (NominalTypeDecl *type) {
@@ -43,7 +42,7 @@ static bool canDeriveConformance(NominalTypeDecl *type) {
43
42
void deriveCaseIterable_enum_getter (AbstractFunctionDecl *funcDecl) {
44
43
auto *parentDC = funcDecl->getDeclContext ();
45
44
auto *parentEnum = parentDC->getAsEnumOrEnumExtensionContext ();
46
- auto enumTy = parentEnum ->getDeclaredTypeInContext ();
45
+ auto enumTy = parentDC ->getDeclaredTypeInContext ();
47
46
auto &C = parentDC->getASTContext ();
48
47
49
48
SmallVector<Expr *, 8 > elExprs;
@@ -69,96 +68,69 @@ static ArraySliceType *computeAllCasesType(NominalTypeDecl *enumType) {
69
68
return ArraySliceType::get (metaTy->getRValueInstanceType ());
70
69
}
71
70
72
- static Type deriveCaseIterable_AllCases (TypeChecker &tc, Decl *parentDecl,
73
- EnumDecl *enumDecl) {
71
+ static Type deriveCaseIterable_AllCases (DerivedConformance &derived) {
74
72
// enum SomeEnum : CaseIterable {
75
73
// @derived
76
74
// typealias AllCases = [SomeEnum]
77
75
// }
78
- auto *rawInterfaceType = computeAllCasesType (enumDecl );
79
- return cast<DeclContext>(parentDecl )->mapTypeIntoContext (rawInterfaceType);
76
+ auto *rawInterfaceType = computeAllCasesType (cast<EnumDecl>(derived. Nominal ) );
77
+ return derived. getConformanceContext ( )->mapTypeIntoContext (rawInterfaceType);
80
78
}
81
79
82
- ValueDecl *DerivedConformance::deriveCaseIterable (TypeChecker &tc,
83
- Decl *parentDecl,
84
- NominalTypeDecl *targetDecl,
85
- ValueDecl *requirement) {
80
+ ValueDecl *DerivedConformance::deriveCaseIterable (ValueDecl *requirement) {
86
81
// Conformance can't be synthesized in an extension.
87
- auto caseIterableProto
88
- = tc.Context .getProtocol (KnownProtocolKind::CaseIterable);
89
- auto caseIterableType = caseIterableProto->getDeclaredType ();
90
- if (targetDecl != parentDecl) {
91
- tc.diagnose (parentDecl->getLoc (), diag::cannot_synthesize_in_extension,
92
- caseIterableType);
82
+ if (checkAndDiagnoseDisallowedContext (requirement))
93
83
return nullptr ;
94
- }
95
84
96
85
// Check that we can actually derive CaseIterable for this type.
97
- if (!canDeriveConformance (targetDecl ))
86
+ if (!canDeriveConformance (Nominal ))
98
87
return nullptr ;
99
88
100
89
// Build the necessary decl.
101
- if (requirement->getBaseName () != tc.Context .Id_allCases ) {
102
- tc.diagnose (requirement->getLoc (),
103
- diag::broken_case_iterable_requirement);
90
+ if (requirement->getBaseName () != TC.Context .Id_allCases ) {
91
+ TC.diagnose (requirement->getLoc (), diag::broken_case_iterable_requirement);
104
92
return nullptr ;
105
93
}
106
94
107
- auto enumDecl = cast<EnumDecl>(targetDecl);
108
- ASTContext &C = tc.Context ;
109
-
95
+ ASTContext &C = TC.Context ;
110
96
111
97
// Define the property.
112
- auto *returnTy = computeAllCasesType (targetDecl );
98
+ auto *returnTy = computeAllCasesType (Nominal );
113
99
114
100
VarDecl *propDecl;
115
101
PatternBindingDecl *pbDecl;
116
- std::tie (propDecl, pbDecl)
117
- = declareDerivedProperty (tc, parentDecl, enumDecl, C.Id_allCases ,
118
- returnTy, returnTy,
102
+ std::tie (propDecl, pbDecl) =
103
+ declareDerivedProperty (C.Id_allCases , returnTy, returnTy,
119
104
/* isStatic=*/ true , /* isFinal=*/ true );
120
105
121
106
// Define the getter.
122
- auto *getterDecl = addGetterToReadOnlyDerivedProperty (tc , propDecl, returnTy);
107
+ auto *getterDecl = addGetterToReadOnlyDerivedProperty (TC , propDecl, returnTy);
123
108
124
109
getterDecl->setBodySynthesizer (&deriveCaseIterable_enum_getter);
125
110
126
- auto dc = cast<IterableDeclContext>(parentDecl);
127
- dc->addMember (getterDecl);
128
- dc->addMember (propDecl);
129
- dc->addMember (pbDecl);
111
+ addMembersToConformanceContext ({getterDecl, propDecl, pbDecl});
130
112
131
113
return propDecl;
132
114
}
133
115
134
- Type DerivedConformance::deriveCaseIterable (TypeChecker &tc, Decl *parentDecl,
135
- NominalTypeDecl *targetDecl,
136
- AssociatedTypeDecl *assocType) {
137
- // Conformance can't be synthesized in an extension.
138
- auto caseIterableProto
139
- = tc.Context .getProtocol (KnownProtocolKind::CaseIterable);
140
- auto caseIterableType = caseIterableProto->getDeclaredType ();
141
- if (targetDecl != parentDecl) {
142
- tc.diagnose (parentDecl->getLoc (), diag::cannot_synthesize_in_extension,
143
- caseIterableType);
116
+ Type DerivedConformance::deriveCaseIterable (AssociatedTypeDecl *assocType) {
117
+ if (checkAndDiagnoseDisallowedContext (assocType))
144
118
return nullptr ;
145
- }
146
119
147
120
// We can only synthesize CaseIterable for enums.
148
- auto enumDecl = dyn_cast<EnumDecl>(targetDecl );
121
+ auto enumDecl = dyn_cast<EnumDecl>(Nominal );
149
122
if (!enumDecl)
150
123
return nullptr ;
151
124
152
125
// Check that we can actually derive CaseIterable for this type.
153
- if (!canDeriveConformance (targetDecl ))
126
+ if (!canDeriveConformance (Nominal ))
154
127
return nullptr ;
155
128
156
- if (assocType->getName () == tc .Context .Id_AllCases ) {
157
- return deriveCaseIterable_AllCases (tc, parentDecl, enumDecl );
129
+ if (assocType->getName () == TC .Context .Id_AllCases ) {
130
+ return deriveCaseIterable_AllCases (* this );
158
131
}
159
132
160
- tc.diagnose (assocType->getLoc (),
161
- diag::broken_case_iterable_requirement);
133
+ TC.diagnose (assocType->getLoc (), diag::broken_case_iterable_requirement);
162
134
return nullptr ;
163
135
}
164
136
0 commit comments