Skip to content

Commit 52c8086

Browse files
committed
Move the defined functions list onto SourceFile
1 parent 5d37c9b commit 52c8086

File tree

4 files changed

+29
-26
lines changed

4 files changed

+29
-26
lines changed

include/swift/AST/SourceFile.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,14 @@ class SourceFile final : public FileUnit {
267267
/// A set of synthesized declarations that need to be type checked.
268268
llvm::SmallVector<Decl *, 8> SynthesizedDecls;
269269

270+
/// The list of functions defined in this file whose bodies have yet to be
271+
/// typechecked. They must be held in this list instead of eagerly validated
272+
/// because their bodies may force us to perform semantic checks of arbitrary
273+
/// complexity, and we currently cannot handle those checks in isolation. E.g.
274+
/// we cannot, in general, perform witness matching on singular requirements
275+
/// unless the entire conformance has been evaluated.
276+
std::vector<AbstractFunctionDecl *> DelayedFunctions;
277+
270278
/// We might perform type checking on the same source file more than once,
271279
/// if its the main file or a REPL instance, so keep track of the last
272280
/// checked synthesized declaration to avoid duplicating work.

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,10 +1166,15 @@ namespace {
11661166
class DeclChecker : public DeclVisitor<DeclChecker> {
11671167
public:
11681168
ASTContext &Ctx;
1169+
SourceFile *SF;
11691170

1170-
explicit DeclChecker(ASTContext &ctx) : Ctx(ctx) {}
1171+
explicit DeclChecker(ASTContext &ctx, SourceFile *SF) : Ctx(ctx), SF(SF) {}
11711172

11721173
ASTContext &getASTContext() const { return Ctx; }
1174+
void addDelayedFunction(AbstractFunctionDecl *AFD) {
1175+
if (!SF) return;
1176+
SF->DelayedFunctions.push_back(AFD);
1177+
}
11731178

11741179
void visit(Decl *decl) {
11751180
if (auto *Stats = getASTContext().Stats)
@@ -1385,7 +1390,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
13851390
TypeChecker::checkDeclAttributes(PBD);
13861391

13871392
bool isInSILMode = false;
1388-
if (auto sourceFile = DC->getParentSourceFile())
1393+
if (auto sourceFile = SF)
13891394
isInSILMode = sourceFile->Kind == SourceFileKind::SIL;
13901395
bool isTypeContext = DC->isTypeContext();
13911396

@@ -1443,7 +1448,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
14431448
// protocol.
14441449
if (var->isStatic() && !isa<ProtocolDecl>(DC)) {
14451450
// ...but don't enforce this for SIL or module interface files.
1446-
switch (DC->getParentSourceFile()->Kind) {
1451+
switch (SF->Kind) {
14471452
case SourceFileKind::Interface:
14481453
case SourceFileKind::SIL:
14491454
return;
@@ -1461,7 +1466,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
14611466

14621467
// Global variables require an initializer in normal source files.
14631468
if (DC->isModuleScopeContext()) {
1464-
switch (DC->getParentSourceFile()->Kind) {
1469+
switch (SF->Kind) {
14651470
case SourceFileKind::Main:
14661471
case SourceFileKind::REPL:
14671472
case SourceFileKind::Interface:
@@ -1994,7 +1999,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
19941999
// Check for circular inheritance within the protocol.
19952000
(void)PD->hasCircularInheritedProtocols();
19962001

1997-
auto *SF = PD->getParentSourceFile();
19982002
if (SF) {
19992003
if (auto *tracker = SF->getReferencedNameTracker()) {
20002004
bool isNonPrivate = (PD->getFormalAccess() > AccessLevel::FilePrivate);
@@ -2150,9 +2154,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
21502154
} else if (shouldSkipBodyTypechecking(FD)) {
21512155
FD->setBodySkipped(FD->getBodySourceRange());
21522156
} else {
2153-
// FIXME: Remove TypeChecker dependency.
2154-
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
2155-
TC.definedFunctions.push_back(FD);
2157+
addDelayedFunction(FD);
21562158
}
21572159

21582160
checkExplicitAvailability(FD);
@@ -2484,9 +2486,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
24842486
} else if (shouldSkipBodyTypechecking(CD)) {
24852487
CD->setBodySkipped(CD->getBodySourceRange());
24862488
} else {
2487-
// FIXME: Remove TypeChecker dependency.
2488-
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
2489-
TC.definedFunctions.push_back(CD);
2489+
addDelayedFunction(CD);
24902490
}
24912491

24922492
checkDefaultArguments(CD->getParameters());
@@ -2501,14 +2501,13 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
25012501
} else if (shouldSkipBodyTypechecking(DD)) {
25022502
DD->setBodySkipped(DD->getBodySourceRange());
25032503
} else {
2504-
// FIXME: Remove TypeChecker dependency.
2505-
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
2506-
TC.definedFunctions.push_back(DD);
2504+
addDelayedFunction(DD);
25072505
}
25082506
}
25092507
};
25102508
} // end anonymous namespace
25112509

25122510
void TypeChecker::typeCheckDecl(Decl *D) {
2513-
DeclChecker(D->getASTContext()).visit(D);
2511+
auto *SF = D->getDeclContext()->getParentSourceFile();
2512+
DeclChecker(D->getASTContext(), SF).visit(D);
25142513
}

lib/Sema/TypeChecker.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -289,16 +289,16 @@ static void bindExtensions(SourceFile &SF) {
289289
// typeCheckDecl().
290290
}
291291

292-
static void typeCheckFunctionsAndExternalDecls(SourceFile &SF, TypeChecker &TC) {
292+
static void typeCheckDelayedFunctions(SourceFile &SF) {
293293
unsigned currentFunctionIdx = 0;
294294
unsigned currentSynthesizedDecl = SF.LastCheckedSynthesizedDecl;
295295
do {
296296
// Type check the body of each of the function in turn. Note that outside
297297
// functions must be visited before nested functions for type-checking to
298298
// work correctly.
299-
for (unsigned n = TC.definedFunctions.size(); currentFunctionIdx != n;
299+
for (unsigned n = SF.DelayedFunctions.size(); currentFunctionIdx != n;
300300
++currentFunctionIdx) {
301-
auto *AFD = TC.definedFunctions[currentFunctionIdx];
301+
auto *AFD = SF.DelayedFunctions[currentFunctionIdx];
302302
assert(!AFD->getDeclContext()->isLocalContext());
303303

304304
TypeChecker::typeCheckAbstractFunctionBody(AFD);
@@ -312,15 +312,15 @@ static void typeCheckFunctionsAndExternalDecls(SourceFile &SF, TypeChecker &TC)
312312
TypeChecker::typeCheckDecl(decl);
313313
}
314314

315-
} while (currentFunctionIdx < TC.definedFunctions.size() ||
315+
} while (currentFunctionIdx < SF.DelayedFunctions.size() ||
316316
currentSynthesizedDecl < SF.SynthesizedDecls.size());
317317

318318

319-
for (AbstractFunctionDecl *FD : llvm::reverse(TC.definedFunctions)) {
319+
for (AbstractFunctionDecl *FD : llvm::reverse(SF.DelayedFunctions)) {
320320
TypeChecker::computeCaptures(FD);
321321
}
322322

323-
TC.definedFunctions.clear();
323+
SF.DelayedFunctions.clear();
324324
}
325325

326326
void swift::performTypeChecking(SourceFile &SF) {
@@ -392,7 +392,7 @@ TypeCheckSourceFileRequest::evaluate(Evaluator &eval, SourceFile *SF) const {
392392
if (SF->Kind == SourceFileKind::REPL && !Ctx.hadError())
393393
TypeChecker::processREPLTopLevel(*SF);
394394

395-
typeCheckFunctionsAndExternalDecls(*SF, TC);
395+
typeCheckDelayedFunctions(*SF);
396396
}
397397

398398
// Checking that benefits from having the whole module available.

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,6 @@ enum class CheckedCastContextKind {
405405
/// The Swift type checker, which takes a parsed AST and performs name binding,
406406
/// type checking, and semantic analysis to produce a type-annotated AST.
407407
class TypeChecker final {
408-
public:
409-
/// The list of function definitions we've encountered.
410-
std::vector<AbstractFunctionDecl *> definedFunctions;
411-
412408
private:
413409
TypeChecker() = default;
414410
~TypeChecker() = default;

0 commit comments

Comments
 (0)