Skip to content

Commit faa66f1

Browse files
committed
Strip the REPLChecker of its TopLevelContext
It's really not important where it manages to find this unique value, but it's gotta get it from somewhere. Shameless steal DiscriminatorFinder from DebuggerTransform to scrobble for the next available discriminator value.
1 parent 88ee618 commit faa66f1

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

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/TypeChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ void swift::performTypeChecking(SourceFile &SF, TopLevelContext &TLC,
375375
// If we're in REPL mode, inject temporary result variables and other stuff
376376
// that the REPL needs to synthesize.
377377
if (SF.Kind == SourceFileKind::REPL && !Ctx.hadError())
378-
TypeChecker::processREPLTopLevel(SF, TLC, StartElem);
378+
TypeChecker::processREPLTopLevel(SF, StartElem);
379379

380380
typeCheckFunctionsAndExternalDecls(SF, TC);
381381
}

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 3 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

0 commit comments

Comments
 (0)