Skip to content

Commit 7993f2f

Browse files
committed
Downgrade the TypeChecker in DerivedConformance to an ASTContext
1 parent 118f68b commit 7993f2f

10 files changed

+153
-159
lines changed

lib/Sema/DerivedConformanceCaseIterable.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,19 @@ ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) {
8787
if (!canDeriveConformance(Nominal))
8888
return nullptr;
8989

90-
ASTContext &C = TC.Context;
91-
9290
// Build the necessary decl.
93-
if (requirement->getBaseName() != C.Id_allCases) {
91+
if (requirement->getBaseName() != Context.Id_allCases) {
9492
requirement->diagnose(diag::broken_case_iterable_requirement);
9593
return nullptr;
9694
}
9795

98-
9996
// Define the property.
10097
auto *returnTy = computeAllCasesType(Nominal);
10198

10299
VarDecl *propDecl;
103100
PatternBindingDecl *pbDecl;
104101
std::tie(propDecl, pbDecl) =
105-
declareDerivedProperty(C.Id_allCases, returnTy, returnTy,
102+
declareDerivedProperty(Context.Id_allCases, returnTy, returnTy,
106103
/*isStatic=*/true, /*isFinal=*/true);
107104

108105
// Define the getter.
@@ -123,11 +120,12 @@ Type DerivedConformance::deriveCaseIterable(AssociatedTypeDecl *assocType) {
123120
if (!canDeriveConformance(Nominal))
124121
return nullptr;
125122

126-
if (assocType->getName() == TC.Context.Id_AllCases) {
123+
if (assocType->getName() == Context.Id_AllCases) {
127124
return deriveCaseIterable_AllCases(*this);
128125
}
129126

130-
TC.diagnose(assocType->getLoc(), diag::broken_case_iterable_requirement);
127+
Context.Diags.diagnose(assocType->getLoc(),
128+
diag::broken_case_iterable_requirement);
131129
return nullptr;
132130
}
133131

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 48 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,13 @@ static CodableConformanceType typeConformsToCodable(DeclContext *context,
9393
/// Returns whether the given variable conforms to the given {En,De}codable
9494
/// protocol.
9595
///
96-
/// \param tc The typechecker to use in validating {En,De}codable conformance.
97-
///
98-
/// \param context The \c DeclContext in which to check conformance.
96+
/// \param DC The \c DeclContext in which to check conformance.
9997
///
10098
/// \param varDecl The \c VarDecl to validate.
10199
///
102100
/// \param proto The \c ProtocolDecl to check conformance to.
103-
static CodableConformanceType varConformsToCodable(TypeChecker &tc,
104-
DeclContext *context,
105-
VarDecl *varDecl,
106-
ProtocolDecl *proto) {
101+
static CodableConformanceType
102+
varConformsToCodable(DeclContext *DC, VarDecl *varDecl, ProtocolDecl *proto) {
107103
// If the decl doesn't yet have a type, we may be seeing it before the type
108104
// checker has gotten around to evaluating its type. For example:
109105
//
@@ -117,8 +113,8 @@ static CodableConformanceType varConformsToCodable(TypeChecker &tc,
117113
// // hasn't yet been evaluated
118114
// }
119115
bool isIUO = varDecl->isImplicitlyUnwrappedOptional();
120-
return typeConformsToCodable(context, varDecl->getValueInterfaceType(),
121-
isIUO, proto);
116+
return typeConformsToCodable(DC, varDecl->getValueInterfaceType(), isIUO,
117+
proto);
122118
}
123119

124120
/// Retrieve the variable name for the purposes of encoding/decoding.
@@ -135,7 +131,6 @@ static Identifier getVarNameForCoding(VarDecl *var) {
135131
/// \param codingKeysDecl The \c CodingKeys enum decl to validate.
136132
static bool validateCodingKeysEnum(DerivedConformance &derived,
137133
EnumDecl *codingKeysDecl) {
138-
auto &tc = derived.TC;
139134
auto conformanceDC = derived.getConformanceContext();
140135

141136
// Look through all var decls in the given type.
@@ -161,8 +156,8 @@ static bool validateCodingKeysEnum(DerivedConformance &derived,
161156
for (auto elt : codingKeysDecl->getAllElements()) {
162157
auto it = properties.find(elt->getName());
163158
if (it == properties.end()) {
164-
tc.diagnose(elt->getLoc(), diag::codable_extraneous_codingkey_case_here,
165-
elt->getName());
159+
elt->diagnose(diag::codable_extraneous_codingkey_case_here,
160+
elt->getName());
166161
// TODO: Investigate typo-correction here; perhaps the case name was
167162
// misspelled and we can provide a fix-it.
168163
propertiesAreValid = false;
@@ -171,17 +166,16 @@ static bool validateCodingKeysEnum(DerivedConformance &derived,
171166

172167
// We have a property to map to. Ensure it's {En,De}codable.
173168
auto conformance =
174-
varConformsToCodable(tc, conformanceDC, it->second, derived.Protocol);
169+
varConformsToCodable(conformanceDC, it->second, derived.Protocol);
175170
switch (conformance) {
176171
case Conforms:
177172
// The property was valid. Remove it from the list.
178173
properties.erase(it);
179174
break;
180175

181176
case DoesNotConform:
182-
tc.diagnose(it->second->getLoc(),
183-
diag::codable_non_conforming_property_here,
184-
derived.getProtocolType(), it->second->getType());
177+
it->second->diagnose(diag::codable_non_conforming_property_here,
178+
derived.getProtocolType(), it->second->getType());
185179
LLVM_FALLTHROUGH;
186180

187181
case TypeNotValidated:
@@ -215,8 +209,8 @@ static bool validateCodingKeysEnum(DerivedConformance &derived,
215209
// The var was not default initializable, and did not have an explicit
216210
// initial value.
217211
propertiesAreValid = false;
218-
tc.diagnose(it->second->getLoc(), diag::codable_non_decoded_property_here,
219-
derived.getProtocolType(), it->first);
212+
it->second->diagnose(diag::codable_non_decoded_property_here,
213+
derived.getProtocolType(), it->first);
220214
}
221215
}
222216

@@ -241,8 +235,7 @@ struct CodingKeysValidity {
241235
///
242236
/// \returns A \c CodingKeysValidity value representing the result of the check.
243237
static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) {
244-
auto &tc = derived.TC;
245-
auto &C = tc.Context;
238+
auto &C = derived.Context;
246239
auto codingKeysDecls =
247240
derived.Nominal->lookupDirect(DeclName(C.Id_CodingKeys));
248241
if (codingKeysDecls.empty())
@@ -255,9 +248,8 @@ static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) {
255248

256249
auto *codingKeysTypeDecl = dyn_cast<TypeDecl>(result);
257250
if (!codingKeysTypeDecl) {
258-
tc.diagnose(result->getLoc(),
259-
diag::codable_codingkeys_type_is_not_an_enum_here,
260-
derived.getProtocolType());
251+
result->diagnose(diag::codable_codingkeys_type_is_not_an_enum_here,
252+
derived.getProtocolType());
261253
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
262254
}
263255

@@ -279,18 +271,18 @@ static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) {
279271
codingKeysTypeDecl->getLoc() :
280272
cast<TypeDecl>(result)->getLoc();
281273

282-
tc.diagnose(loc, diag::codable_codingkeys_type_does_not_conform_here,
283-
derived.getProtocolType());
274+
C.Diags.diagnose(loc, diag::codable_codingkeys_type_does_not_conform_here,
275+
derived.getProtocolType());
284276

285277
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
286278
}
287279

288280
// CodingKeys must be an enum for synthesized conformance.
289281
auto *codingKeysEnum = dyn_cast<EnumDecl>(codingKeysTypeDecl);
290282
if (!codingKeysEnum) {
291-
tc.diagnose(codingKeysTypeDecl->getLoc(),
292-
diag::codable_codingkeys_type_is_not_an_enum_here,
293-
derived.getProtocolType());
283+
codingKeysTypeDecl->diagnose(
284+
diag::codable_codingkeys_type_is_not_an_enum_here,
285+
derived.getProtocolType());
294286
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
295287
}
296288

@@ -303,8 +295,7 @@ static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) {
303295
///
304296
/// If able to synthesize the enum, adds it directly to \c derived.Nominal.
305297
static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
306-
auto &tc = derived.TC;
307-
auto &C = tc.Context;
298+
auto &C = derived.Context;
308299
// Create CodingKeys in the parent type always, because both
309300
// Encodable and Decodable might want to use it, and they may have
310301
// different conditional bounds. CodingKeys is simple and can't
@@ -348,7 +339,7 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
348339
// concurrently checking the variables for the current protocol
349340
// conformance being synthesized, for which we use the conformance
350341
// context, not the type.
351-
auto conformance = varConformsToCodable(tc, derived.getConformanceContext(),
342+
auto conformance = varConformsToCodable(derived.getConformanceContext(),
352343
varDecl, derived.Protocol);
353344
switch (conformance) {
354345
case Conforms:
@@ -363,9 +354,8 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
363354
}
364355

365356
case DoesNotConform:
366-
tc.diagnose(varDecl->getLoc(),
367-
diag::codable_non_conforming_property_here,
368-
derived.getProtocolType(), varDecl->getType());
357+
varDecl->diagnose(diag::codable_non_conforming_property_here,
358+
derived.getProtocolType(), varDecl->getType());
369359
LLVM_FALLTHROUGH;
370360

371361
case TypeNotValidated:
@@ -380,7 +370,10 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
380370
return nullptr;
381371

382372
// Forcibly derive conformance to CodingKey.
383-
tc.checkConformancesInContext(enumDecl, enumDecl);
373+
//
374+
// FIXME: Drop the dependency on the type checker.
375+
auto *tc = static_cast<TypeChecker *>(C.getLazyResolver());
376+
tc->checkConformancesInContext(enumDecl, enumDecl);
384377

385378
// Add to the type.
386379
target->addMember(enumDecl);
@@ -706,7 +699,7 @@ deriveBodyEncodable_encode(AbstractFunctionDecl *encodeDecl, void *) {
706699
///
707700
/// Adds the function declaration to the given type before returning it.
708701
static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) {
709-
auto &C = derived.TC.Context;
702+
auto &C = derived.Context;
710703
auto conformanceDC = derived.getConformanceContext();
711704

712705
// Expected type: (Self) -> (Encoder) throws -> ()
@@ -985,7 +978,7 @@ deriveBodyDecodable_init(AbstractFunctionDecl *initDecl, void *) {
985978
///
986979
/// Adds the function declaration to the given type before returning it.
987980
static ValueDecl *deriveDecodable_init(DerivedConformance &derived) {
988-
auto &C = derived.TC.Context;
981+
auto &C = derived.Context;
989982

990983
auto classDecl = dyn_cast<ClassDecl>(derived.Nominal);
991984
auto conformanceDC = derived.getConformanceContext();
@@ -1056,8 +1049,6 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) {
10561049
//
10571050
// If the required initializer is not available, we shouldn't attempt to
10581051
// synthesize CodingKeys.
1059-
auto &tc = derived.TC;
1060-
ASTContext &C = tc.Context;
10611052
auto proto = derived.Protocol;
10621053
auto *classDecl = dyn_cast<ClassDecl>(derived.Nominal);
10631054
if (proto->isSpecificProtocol(KnownProtocolKind::Decodable) && classDecl) {
@@ -1072,8 +1063,9 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) {
10721063
// super.init() must be accessible.
10731064
// Passing an empty params array constructs a compound name with no
10741065
// arguments (as opposed to a simple name when omitted).
1075-
memberName = DeclName(C, DeclBaseName::createConstructor(),
1076-
ArrayRef<Identifier>());
1066+
memberName =
1067+
DeclName(derived.Context, DeclBaseName::createConstructor(),
1068+
ArrayRef<Identifier>());
10771069
}
10781070

10791071
auto result =
@@ -1139,9 +1131,9 @@ ValueDecl *DerivedConformance::deriveEncodable(ValueDecl *requirement) {
11391131
if (!isa<StructDecl>(Nominal) && !isa<ClassDecl>(Nominal))
11401132
return nullptr;
11411133

1142-
if (requirement->getBaseName() != TC.Context.Id_encode) {
1134+
if (requirement->getBaseName() != Context.Id_encode) {
11431135
// Unknown requirement.
1144-
TC.diagnose(requirement->getLoc(), diag::broken_encodable_requirement);
1136+
requirement->diagnose(diag::broken_encodable_requirement);
11451137
return nullptr;
11461138
}
11471139

@@ -1163,12 +1155,12 @@ ValueDecl *DerivedConformance::deriveEncodable(ValueDecl *requirement) {
11631155
// diagnostics, then potentially collect notes. If we succeed in
11641156
// synthesizing Encodable, we can cancel the transaction and get rid of the
11651157
// fake failures.
1166-
DiagnosticTransaction diagnosticTransaction(TC.Context.Diags);
1167-
TC.diagnose(ConformanceDecl, diag::type_does_not_conform,
1168-
Nominal->getDeclaredType(), getProtocolType());
1169-
TC.diagnose(requirement, diag::no_witnesses, diag::RequirementKind::Func,
1170-
requirement->getFullName(), getProtocolType(),
1171-
/*AddFixIt=*/false);
1158+
DiagnosticTransaction diagnosticTransaction(Context.Diags);
1159+
ConformanceDecl->diagnose(diag::type_does_not_conform,
1160+
Nominal->getDeclaredType(), getProtocolType());
1161+
requirement->diagnose(diag::no_witnesses, diag::RequirementKind::Func,
1162+
requirement->getFullName(), getProtocolType(),
1163+
/*AddFixIt=*/false);
11721164

11731165
// Check other preconditions for synthesized conformance.
11741166
// This synthesizes a CodingKeys enum if possible.
@@ -1187,7 +1179,7 @@ ValueDecl *DerivedConformance::deriveDecodable(ValueDecl *requirement) {
11871179

11881180
if (requirement->getBaseName() != DeclBaseName::createConstructor()) {
11891181
// Unknown requirement.
1190-
TC.diagnose(requirement->getLoc(), diag::broken_decodable_requirement);
1182+
requirement->diagnose(diag::broken_decodable_requirement);
11911183
return nullptr;
11921184
}
11931185

@@ -1199,12 +1191,12 @@ ValueDecl *DerivedConformance::deriveDecodable(ValueDecl *requirement) {
11991191
// diagnostics produced by canSynthesize and deriveDecodable_init to produce
12001192
// them in the right order -- see the comment in deriveEncodable for
12011193
// background on this transaction.
1202-
DiagnosticTransaction diagnosticTransaction(TC.Context.Diags);
1203-
TC.diagnose(ConformanceDecl->getLoc(), diag::type_does_not_conform,
1204-
Nominal->getDeclaredType(), getProtocolType());
1205-
TC.diagnose(requirement, diag::no_witnesses,
1206-
diag::RequirementKind::Constructor, requirement->getFullName(),
1207-
getProtocolType(), /*AddFixIt=*/false);
1194+
DiagnosticTransaction diagnosticTransaction(Context.Diags);
1195+
ConformanceDecl->diagnose(diag::type_does_not_conform,
1196+
Nominal->getDeclaredType(), getProtocolType());
1197+
requirement->diagnose(diag::no_witnesses, diag::RequirementKind::Constructor,
1198+
requirement->getFullName(), getProtocolType(),
1199+
/*AddFixIt=*/false);
12081200

12091201
// Check other preconditions for synthesized conformance.
12101202
// This synthesizes a CodingKeys enum if possible.

0 commit comments

Comments
 (0)