Skip to content

Commit 3975e72

Browse files
authored
Merge pull request #28246 from CodaFi/contextual-equivalence
Drop the TopLevelContext from the high-level type checker entrypoints
2 parents 3b50749 + 09c7c74 commit 3975e72

File tree

11 files changed

+70
-43
lines changed

11 files changed

+70
-43
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ class ASTContext final {
277277
/// The # of times we have performed typo correction.
278278
unsigned NumTypoCorrections = 0;
279279

280+
/// The next auto-closure discriminator. This needs to be preserved
281+
/// across invocations of both the parser and the type-checker.
282+
unsigned NextAutoClosureDiscriminator = 0;
283+
280284
private:
281285
/// The current generation number, which reflects the number of
282286
/// times that external modules have been loaded.

include/swift/Parse/LocalContext.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,7 @@ class LocalContext {
6161
};
6262

6363
/// Information associated with parsing the top-level context.
64-
class TopLevelContext : public LocalContext {
65-
public:
66-
/// The next auto-closure discriminator. This needs to be preserved
67-
/// across invocations of both the parser and the type-checker.
68-
unsigned NextAutoClosureDiscriminator = 0;
69-
};
64+
class TopLevelContext : public LocalContext {};
7065

7166
} // end namespace swift
7267

include/swift/Subsystems.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ namespace swift {
168168
/// Once parsing and name-binding are complete this optionally walks the ASTs
169169
/// to add calls to externally provided functions that simulate
170170
/// "program counter"-like debugging events.
171-
void performPCMacro(SourceFile &SF, TopLevelContext &TLC);
171+
void performPCMacro(SourceFile &SF);
172172

173173
/// Creates a type checker instance on the given AST context, if it
174174
/// doesn't already have one.
@@ -184,8 +184,7 @@ namespace swift {
184184
///
185185
/// \param StartElem Where to start for incremental type-checking in the main
186186
/// source file.
187-
void performTypeChecking(SourceFile &SF, TopLevelContext &TLC,
188-
unsigned StartElem = 0);
187+
void performTypeChecking(SourceFile &SF, unsigned StartElem = 0);
189188

190189
/// Now that we have type-checked an entire module, perform any type
191190
/// checking that requires the full module, e.g., Objective-C method

lib/Frontend/Frontend.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,10 @@ void CompilerInstance::parseAndCheckTypesUpTo(
858858
return;
859859
}
860860

861-
performTypeChecking(SF, PersistentState->getTopLevelContext());
861+
performTypeChecking(SF);
862862

863863
if (!Context->hadError() && Invocation.getFrontendOptions().PCMacro) {
864-
performPCMacro(SF, PersistentState->getTopLevelContext());
864+
performPCMacro(SF);
865865
}
866866

867867
// Playground transform knows to look out for PCMacro's changes and not
@@ -975,8 +975,7 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
975975
performNameBinding(MainFile, CurTUElem);
976976
break;
977977
case SourceFile::TypeChecked:
978-
performTypeChecking(MainFile, PersistentState->getTopLevelContext(),
979-
CurTUElem);
978+
performTypeChecking(MainFile, CurTUElem);
980979
break;
981980
}
982981
}

lib/IDE/REPLCodeCompletion.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,7 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
212212
do {
213213
parseIntoSourceFile(SF, *BufferID, &Done, nullptr, &PersistentState);
214214
} while (!Done);
215-
performTypeChecking(SF, PersistentState.getTopLevelContext(),
216-
OriginalDeclCount);
215+
performTypeChecking(SF, OriginalDeclCount);
217216

218217
performCodeCompletionSecondPass(PersistentState, *CompletionCallbacksFactory);
219218

lib/Immediate/REPL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ typeCheckREPLInput(ModuleDecl *MostRecentModule, StringRef Name,
193193
parseIntoSourceFile(REPLInputFile, BufferID, &Done, nullptr,
194194
&PersistentState);
195195
} while (!Done);
196-
performTypeChecking(REPLInputFile, PersistentState.getTopLevelContext());
196+
performTypeChecking(REPLInputFile);
197197
return REPLModule;
198198
}
199199

lib/Sema/PCMacro.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -665,14 +665,13 @@ class Instrumenter : InstrumenterBase {
665665

666666
} // end anonymous namespace
667667

668-
void swift::performPCMacro(SourceFile &SF, TopLevelContext &TLC) {
668+
void swift::performPCMacro(SourceFile &SF) {
669669
class ExpressionFinder : public ASTWalker {
670670
private:
671671
unsigned TmpNameIndex = 0;
672-
TopLevelContext &TLC;
673672

674673
public:
675-
ExpressionFinder(TopLevelContext &TLC) : TLC(TLC) {}
674+
ExpressionFinder() = default;
676675

677676
bool walkToDeclPre(Decl *D) override {
678677
ASTContext &ctx = D->getASTContext();
@@ -692,7 +691,7 @@ void swift::performPCMacro(SourceFile &SF, TopLevelContext &TLC) {
692691
if (NewBody != Body) {
693692
TLCD->setBody(NewBody);
694693
TypeChecker::checkTopLevelErrorHandling(TLCD);
695-
TypeChecker::contextualizeTopLevelCode(TLC, TLCD);
694+
TypeChecker::contextualizeTopLevelCode(TLCD);
696695
}
697696
return false;
698697
}
@@ -702,7 +701,7 @@ void swift::performPCMacro(SourceFile &SF, TopLevelContext &TLC) {
702701
}
703702
};
704703

705-
ExpressionFinder EF(TLC);
704+
ExpressionFinder EF;
706705
for (Decl *D : SF.Decls) {
707706
D->walk(EF);
708707
}

lib/Sema/TypeCheckREPL.cpp

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "TypeChecker.h"
1818
#include "swift/AST/ASTContext.h"
1919
#include "swift/AST/ASTVisitor.h"
20+
#include "swift/AST/ASTWalker.h"
2021
#include "swift/AST/DiagnosticsFrontend.h"
2122
#include "swift/AST/Expr.h"
2223
#include "swift/AST/NameLookup.h"
@@ -30,6 +31,36 @@
3031
using namespace swift;
3132

3233
namespace {
34+
35+
/// Find available closure discriminators.
36+
///
37+
/// The parser typically takes care of assigning unique discriminators to
38+
/// closures, but the parser is unavailable to this transform.
39+
class DiscriminatorFinder : public ASTWalker {
40+
unsigned NextDiscriminator = 0;
41+
42+
public:
43+
Expr *walkToExprPost(Expr *E) override {
44+
auto *ACE = dyn_cast<AbstractClosureExpr>(E);
45+
if (!ACE)
46+
return E;
47+
48+
unsigned Discriminator = ACE->getDiscriminator();
49+
assert(Discriminator != AbstractClosureExpr::InvalidDiscriminator &&
50+
"Existing closures should have valid discriminators");
51+
if (Discriminator >= NextDiscriminator)
52+
NextDiscriminator = Discriminator + 1;
53+
return E;
54+
}
55+
56+
// Get the next available closure discriminator.
57+
unsigned getNextDiscriminator() {
58+
if (NextDiscriminator == AbstractClosureExpr::InvalidDiscriminator)
59+
llvm::report_fatal_error("Out of valid closure discriminators");
60+
return NextDiscriminator++;
61+
}
62+
};
63+
3364
struct REPLContext {
3465
ASTContext &Context;
3566
SourceFile &SF;
@@ -182,14 +213,14 @@ struct PatternBindingPrintLHS : public ASTVisitor<PatternBindingPrintLHS> {
182213

183214
namespace {
184215
class REPLChecker : public REPLContext {
185-
TopLevelContext &TLC;
216+
DiscriminatorFinder &DF;
186217

187218
/// The index of the next response metavariable to bind to a REPL result.
188219
unsigned NextResponseVariableIndex = 0;
189220

190221
public:
191-
REPLChecker(SourceFile &SF, TopLevelContext &TLC)
192-
: REPLContext(SF), TLC(TLC) {}
222+
REPLChecker(SourceFile &SF, DiscriminatorFinder &DF)
223+
: REPLContext(SF), DF(DF) {}
193224

194225
void processREPLTopLevelExpr(Expr *E);
195226
void processREPLTopLevelPatternBinding(PatternBindingDecl *PBD);
@@ -222,7 +253,7 @@ void REPLChecker::generatePrintOfExpression(StringRef NameStr, Expr *E) {
222253
Arg->setSpecifier(ParamSpecifier::Default);
223254
auto params = ParameterList::createWithoutLoc(Arg);
224255

225-
unsigned discriminator = TLC.claimNextClosureDiscriminator();
256+
unsigned discriminator = DF.getNextDiscriminator();
226257

227258
ClosureExpr *CE =
228259
new (Context) ClosureExpr(params, SourceLoc(), SourceLoc(), SourceLoc(),
@@ -429,13 +460,18 @@ Identifier REPLChecker::getNextResponseVariableName(DeclContext *DC) {
429460
/// processREPLTopLevel - This is called after we've parsed and typechecked some
430461
/// new decls at the top level. We inject code to print out expressions and
431462
/// pattern bindings the are evaluated.
432-
void TypeChecker::processREPLTopLevel(SourceFile &SF, TopLevelContext &TLC,
433-
unsigned FirstDecl) {
463+
void TypeChecker::processREPLTopLevel(SourceFile &SF, unsigned FirstDecl) {
464+
// Walk over all decls in the file to find the next available closure
465+
// discriminator.
466+
DiscriminatorFinder DF;
467+
for (Decl *D : SF.Decls)
468+
D->walk(DF);
469+
434470
// Move new declarations out.
435471
std::vector<Decl *> NewDecls(SF.Decls.begin()+FirstDecl, SF.Decls.end());
436472
SF.Decls.resize(FirstDecl);
437473

438-
REPLChecker RC(SF, TLC);
474+
REPLChecker RC(SF, DF);
439475

440476
// Loop over each of the new decls, processing them, adding them back to
441477
// the Decls list.
@@ -455,7 +491,7 @@ void TypeChecker::processREPLTopLevel(SourceFile &SF, TopLevelContext &TLC,
455491
if (auto *PBD = dyn_cast<PatternBindingDecl>(D))
456492
RC.processREPLTopLevelPatternBinding(PBD);
457493

458-
contextualizeTopLevelCode(TLC, TLCD);
494+
TypeChecker::contextualizeTopLevelCode(TLCD);
459495
}
460496

461497
SF.clearLookupCache();

lib/Sema/TypeCheckStmt.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,14 @@ bool TypeChecker::contextualizeInitializer(Initializer *DC, Expr *E) {
231231
return CC.hasAutoClosures();
232232
}
233233

234-
void TypeChecker::contextualizeTopLevelCode(TopLevelContext &TLC,
235-
TopLevelCodeDecl *TLCD) {
236-
unsigned nextDiscriminator = TLC.NextAutoClosureDiscriminator;
234+
void TypeChecker::contextualizeTopLevelCode(TopLevelCodeDecl *TLCD) {
235+
auto &Context = TLCD->DeclContext::getASTContext();
236+
unsigned nextDiscriminator = Context.NextAutoClosureDiscriminator;
237237
ContextualizeClosures CC(TLCD, nextDiscriminator);
238238
TLCD->getBody()->walk(CC);
239-
assert(nextDiscriminator == TLC.NextAutoClosureDiscriminator &&
239+
assert(nextDiscriminator == Context.NextAutoClosureDiscriminator &&
240240
"reentrant/concurrent invocation of contextualizeTopLevelCode?");
241-
TLC.NextAutoClosureDiscriminator = CC.NextDiscriminator;
241+
Context.NextAutoClosureDiscriminator = CC.NextDiscriminator;
242242
}
243243

244244
/// Emits an error with a fixit for the case of unnecessary cast over a

lib/Sema/TypeChecker.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,7 @@ static void typeCheckFunctionsAndExternalDecls(SourceFile &SF, TypeChecker &TC)
315315
TC.definedFunctions.clear();
316316
}
317317

318-
void swift::performTypeChecking(SourceFile &SF, TopLevelContext &TLC,
319-
unsigned StartElem) {
318+
void swift::performTypeChecking(SourceFile &SF, unsigned StartElem) {
320319
if (SF.ASTStage == SourceFile::TypeChecked)
321320
return;
322321

@@ -366,7 +365,7 @@ void swift::performTypeChecking(SourceFile &SF, TopLevelContext &TLC,
366365
if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
367366
// Immediately perform global name-binding etc.
368367
TypeChecker::typeCheckTopLevelCodeDecl(TLCD);
369-
TypeChecker::contextualizeTopLevelCode(TLC, TLCD);
368+
TypeChecker::contextualizeTopLevelCode(TLCD);
370369
} else {
371370
TypeChecker::typeCheckDecl(D);
372371
}
@@ -375,7 +374,7 @@ void swift::performTypeChecking(SourceFile &SF, TopLevelContext &TLC,
375374
// If we're in REPL mode, inject temporary result variables and other stuff
376375
// that the REPL needs to synthesize.
377376
if (SF.Kind == SourceFileKind::REPL && !Ctx.hadError())
378-
TypeChecker::processREPLTopLevel(SF, TLC, StartElem);
377+
TypeChecker::processREPLTopLevel(SF, StartElem);
379378

380379
typeCheckFunctionsAndExternalDecls(SF, TC);
381380
}

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ namespace swift {
3838
class GenericSignatureBuilder;
3939
class NominalTypeDecl;
4040
class NormalProtocolConformance;
41-
class TopLevelContext;
4241
class TypeChecker;
4342
class TypeResolution;
4443
class TypeResolutionOptions;
@@ -819,8 +818,7 @@ class TypeChecker final {
819818

820819
static void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD);
821820

822-
static void processREPLTopLevel(SourceFile &SF, TopLevelContext &TLC,
823-
unsigned StartElem);
821+
static void processREPLTopLevel(SourceFile &SF, unsigned StartElem);
824822

825823
static void typeCheckDecl(Decl *D);
826824

@@ -1159,8 +1157,7 @@ class TypeChecker final {
11591157
///
11601158
/// \returns true if any closures were found
11611159
static bool contextualizeInitializer(Initializer *DC, Expr *init);
1162-
static void contextualizeTopLevelCode(TopLevelContext &TLC,
1163-
TopLevelCodeDecl *TLCD);
1160+
static void contextualizeTopLevelCode(TopLevelCodeDecl *TLCD);
11641161

11651162
/// Return the type-of-reference of the given value.
11661163
///

0 commit comments

Comments
 (0)