Skip to content

Commit

Permalink
Merge pull request #19825 from DougGregor/immortal-type-checker
Browse files Browse the repository at this point in the history
[Type checker] Keep the type checker alive as long as the ASTContext is.
  • Loading branch information
DougGregor committed Oct 11, 2018
2 parents 2a18ea7 + 264b680 commit a9315e9
Show file tree
Hide file tree
Showing 19 changed files with 162 additions and 186 deletions.
23 changes: 23 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,35 @@ class ASTContext final {
/// Set a new stats reporter.
void setStatsReporter(UnifiedStatsReporter *stats);

/// Creates a new lazy resolver by passing the ASTContext and the other
/// given arguments to a newly-allocated instance of \c ResolverType.
///
/// \returns true if a new lazy resolver was created, false if there was
/// already a lazy resolver registered.
template<typename ResolverType, typename ... Args>
bool createLazyResolverIfMissing(Args && ...args) {
if (getLazyResolver())
return false;

setLazyResolver(new ResolverType(*this, std::forward<Args>(args)...));
return true;
}

/// Remove the lazy resolver, if there is one.
///
/// FIXME: We probably don't ever want to do this.
void removeLazyResolver() {
setLazyResolver(nullptr);
}

/// Retrieve the lazy resolver for this context.
LazyResolver *getLazyResolver() const;

private:
/// Set the lazy resolver for this context.
void setLazyResolver(LazyResolver *resolver);

public:
/// Add a lazy parser for resolving members later.
void addLazyParser(LazyMemberParser *parser);

Expand Down
11 changes: 6 additions & 5 deletions include/swift/Sema/IDETypeChecking.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace swift {
class ExtensionDecl;
class ProtocolDecl;
class Type;
class TypeChecker;
class DeclContext;
class ConcreteDeclRef;
class ValueDecl;
Expand Down Expand Up @@ -123,11 +124,11 @@ namespace swift {
/// \returns true on success, false on error.
bool typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD);

/// A unique_ptr for LazyResolver that can perform additional cleanup.
using OwnedResolver = std::unique_ptr<LazyResolver, void(*)(LazyResolver*)>;

/// Creates a lazy type resolver for use in lookups.
OwnedResolver createLazyResolver(ASTContext &Ctx);
/// Creates a type checker instance on the given AST context, if it
/// doesn't already have one.
///
/// \returns a reference to the type checker instance.
TypeChecker &createTypeChecker(ASTContext &Ctx);

struct ExtensionInfo {
// The extension with the declarations to apply.
Expand Down
13 changes: 6 additions & 7 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
ASTContext::Implementation::Implementation()
: IdentifierTable(Allocator), TheSyntaxArena(new SyntaxArena()) {}
ASTContext::Implementation::~Implementation() {
delete Resolver;

for (auto &cleanup : Cleanups)
cleanup();
}
Expand Down Expand Up @@ -579,13 +581,10 @@ LazyResolver *ASTContext::getLazyResolver() const {

/// Set the lazy resolver for this context.
void ASTContext::setLazyResolver(LazyResolver *resolver) {
if (resolver) {
assert(getImpl().Resolver == nullptr && "already have a resolver");
getImpl().Resolver = resolver;
} else {
assert(getImpl().Resolver != nullptr && "no resolver to remove");
getImpl().Resolver = resolver;
}
if (auto existing = getImpl().Resolver)
delete existing;

getImpl().Resolver = resolver;
}

void ASTContext::addLazyParser(LazyMemberParser *lazyParser) {
Expand Down
2 changes: 1 addition & 1 deletion lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
TheSILModule ? &SILContext : nullptr, &PersistentState,
DelayedParseCB);

if (mainIsPrimary) {
if (mainIsPrimary && (Done || CurTUElem < MainFile.Decls.size())) {
switch (LimitStage) {
case SourceFile::Parsing:
case SourceFile::Parsed:
Expand Down
42 changes: 19 additions & 23 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,7 @@ static bool hasTrivialTrailingClosure(const FuncDecl *FD,
class CompletionLookup final : public swift::VisibleDeclConsumer {
CodeCompletionResultSink &Sink;
ASTContext &Ctx;
OwnedResolver TypeResolver;
LazyResolver *TypeResolver = nullptr;
const DeclContext *CurrDeclContext;
ClangImporter *Importer;
CodeCompletionContext *CompletionContext;
Expand Down Expand Up @@ -1723,11 +1723,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
ASTContext &Ctx,
const DeclContext *CurrDeclContext,
CodeCompletionContext *CompletionContext = nullptr)
: Sink(Sink), Ctx(Ctx),
TypeResolver(createLazyResolver(Ctx)), CurrDeclContext(CurrDeclContext),
: Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
Importer(static_cast<ClangImporter *>(CurrDeclContext->getASTContext().
getClangModuleLoader())),
CompletionContext(CompletionContext) {
(void)createTypeChecker(Ctx);
TypeResolver = Ctx.getLazyResolver();

// Determine if we are doing code completion inside a static method.
if (CurrDeclContext) {
Expand All @@ -1737,10 +1738,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
}
}

void discardTypeResolver() {
TypeResolver.reset();
}

void setHaveDot(SourceLoc DotLoc) {
HaveDot = true;
this->DotLoc = DotLoc;
Expand Down Expand Up @@ -2095,7 +2092,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
if (Conformance && Conformance->isConcrete()) {
return Conformance->getConcrete()
->getTypeWitness(const_cast<AssociatedTypeDecl *>(ATD),
TypeResolver.get());
nullptr);
}
}
}
Expand Down Expand Up @@ -2624,7 +2621,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
SmallVector<ValueDecl *, 16> initializers;
if (CurrDeclContext->lookupQualified(type, DeclBaseName::createConstructor(),
NL_QualifiedDefault,
TypeResolver.get(), initializers)) {
TypeResolver, initializers)) {
for (auto *init : initializers) {
if (shouldHideDeclFromCompletionResults(init))
continue;
Expand Down Expand Up @@ -3121,7 +3118,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
if (isIUO) {
if (Type Unwrapped = ExprType->getOptionalObjectType()) {
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
TypeResolver.get(), IncludeInstanceMembers);
TypeResolver, IncludeInstanceMembers);
return true;
}
assert(IsUnwrappedOptional && "IUOs should be optional if not bound/forced");
Expand All @@ -3141,7 +3138,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
CodeCompletionResult::MaxNumBytesToErase) {
if (!tryTupleExprCompletions(Unwrapped)) {
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
TypeResolver.get(),
TypeResolver,
IncludeInstanceMembers);
}
}
Expand Down Expand Up @@ -3181,7 +3178,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
tryUnwrappedCompletions(ExprType, isIUO);

lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext,
TypeResolver.get(), IncludeInstanceMembers);
TypeResolver, IncludeInstanceMembers);
}

template <typename T>
Expand Down Expand Up @@ -3690,7 +3687,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
Kind = LookupKind::ValueInDeclContext;
NeedLeadingDot = false;
FilteredDeclConsumer Consumer(*this, Filter);
lookupVisibleDecls(Consumer, CurrDeclContext, TypeResolver.get(),
lookupVisibleDecls(Consumer, CurrDeclContext, TypeResolver,
/*IncludeTopLevel=*/IncludeTopLevel, Loc);
if (RequestCache)
RequestedCachedResults = RequestedResultsTy::toplevelResults();
Expand Down Expand Up @@ -3823,7 +3820,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
llvm::SaveAndRestore<Type> SaveType(ExprType, baseType);
llvm::SaveAndRestore<bool> SaveUnresolved(IsUnresolvedMember, true);
lookupVisibleMemberDecls(consumer, baseType, CurrDeclContext,
TypeResolver.get(),
TypeResolver,
/*includeInstanceMembers=*/false);
}

Expand Down Expand Up @@ -4026,7 +4023,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
NeedLeadingDot = !HaveDot;
Type MetaBase = MetatypeType::get(BaseType);
lookupVisibleMemberDecls(*this, MetaBase,
CurrDeclContext, TypeResolver.get(),
CurrDeclContext, TypeResolver,
IncludeInstanceMembers);
addKeyword("Type", MetaBase);
}
Expand Down Expand Up @@ -4090,7 +4087,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {

void getTypeCompletionsInDeclContext(SourceLoc Loc) {
Kind = LookupKind::TypeInDeclContext;
lookupVisibleDecls(*this, CurrDeclContext, TypeResolver.get(),
lookupVisibleDecls(*this, CurrDeclContext, TypeResolver,
/*IncludeTopLevel=*/false, Loc);

RequestedCachedResults =
Expand Down Expand Up @@ -4125,8 +4122,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {

class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
CodeCompletionResultSink &Sink;
OwnedResolver TypeResolver;
const DeclContext *CurrDeclContext;
LazyResolver *TypeResolver;
SmallVectorImpl<StringRef> &ParsedKeywords;

bool hasFuncIntroducer = false;
Expand All @@ -4141,8 +4138,11 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
const DeclContext *CurrDeclContext,
SmallVectorImpl<StringRef> &ParsedKeywords)
: Sink(Sink), TypeResolver(createLazyResolver(Ctx)),
: Sink(Sink),
CurrDeclContext(CurrDeclContext), ParsedKeywords(ParsedKeywords) {
(void)createTypeChecker(Ctx);
TypeResolver = Ctx.getLazyResolver();

hasFuncIntroducer = isKeywordSpecified("func");
hasVarIntroducer = isKeywordSpecified("var") ||
isKeywordSpecified("let");
Expand Down Expand Up @@ -4414,7 +4414,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
Type CurrTy = CurrDeclContext->getDeclaredTypeInContext();
if (CurrTy && !CurrTy->is<ErrorType>()) {
lookupVisibleMemberDecls(*this, CurrTy, CurrDeclContext,
TypeResolver.get(),
TypeResolver,
/*includeInstanceMembers=*/false);
addDesignatedInitializers(CurrTy);
addAssociatedTypes(CurrTy);
Expand Down Expand Up @@ -5576,7 +5576,6 @@ void CodeCompletionCallbacksImpl::doneParsing() {
}

case CompletionKind::NominalMemberBeginning: {
Lookup.discardTypeResolver();
CompletionOverrideLookup OverrideLookup(CompletionContext.getResultSink(),
P.Context, CurDeclContext,
ParsedKeywords);
Expand Down Expand Up @@ -5738,15 +5737,12 @@ void CodeCompletionCallbacksImpl::doneParsing() {
};

if (Request.TheModule) {
Lookup.discardTypeResolver();

// FIXME: actually check imports.
const_cast<ModuleDecl*>(Request.TheModule)
->forAllVisibleModules({}, handleImport);
} else {
// Add results from current module.
Lookup.getToplevelCompletions(Request.OnlyTypes);
Lookup.discardTypeResolver();

// Add results for all imported modules.
SmallVector<ModuleDecl::ImportedModule, 4> Imports;
Expand Down
27 changes: 6 additions & 21 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3664,13 +3664,7 @@ bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
BaseTy->hasUnboundGenericType())
return true;

std::unique_ptr<TypeChecker> CreatedTC;
// If the current ast context has no type checker, create one for it.
auto *TC = static_cast<TypeChecker*>(DC.getASTContext().getLazyResolver());
if (!TC) {
CreatedTC.reset(new TypeChecker(DC.getASTContext()));
TC = CreatedTC.get();
}
TypeChecker *TC = &createTypeChecker(DC.getASTContext());

ConstraintSystemOptions Options;
ConstraintSystem CS(*TC, &DC, Options);
Expand All @@ -3696,14 +3690,9 @@ bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
static bool canSatisfy(Type type1, Type type2, bool openArchetypes,
ConstraintKind kind, DeclContext *dc) {
std::unique_ptr<TypeChecker> CreatedTC;
// If the current ASTContext has no type checker, create one for it.
auto *TC = static_cast<TypeChecker*>(dc->getASTContext().getLazyResolver());
if (!TC) {
CreatedTC.reset(new TypeChecker(dc->getASTContext()));
TC = CreatedTC.get();
}
return TC->typesSatisfyConstraint(type1, type2, openArchetypes, kind, dc,
/*unwrappedIUO=*/nullptr);
auto &TC = TypeChecker::createForContext(dc->getASTContext());
return TC.typesSatisfyConstraint(type1, type2, openArchetypes, kind, dc,
/*unwrappedIUO=*/nullptr);
}

bool swift::canPossiblyEqual(Type T1, Type T2, DeclContext &DC) {
Expand Down Expand Up @@ -3765,12 +3754,8 @@ swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name) {
ResolvedMemberResult Result;
std::unique_ptr<TypeChecker> CreatedTC;
// If the current ast context has no type checker, create one for it.
auto *TC = static_cast<TypeChecker*>(DC.getASTContext().getLazyResolver());
if (!TC) {
CreatedTC.reset(new TypeChecker(DC.getASTContext()));
TC = CreatedTC.get();
}
ConstraintSystem CS(*TC, &DC, None);
auto &TC = TypeChecker::createForContext(DC.getASTContext());
ConstraintSystem CS(TC, &DC, None);

// Look up all members of BaseTy with the given Name.
MemberLookupResult LookupResult = CS.performMemberLookup(
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/DebuggerTestingTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ class DebuggerTestingTransform : public ASTWalker {
CheckExpectExpr->setThrows(false);

// Create the closure.
TypeChecker TC{Ctx};
TypeChecker &TC = TypeChecker::createForContext(Ctx);
auto *Params = ParameterList::createEmpty(Ctx);
auto *Closure = new (Ctx)
ClosureExpr(Params, SourceLoc(), SourceLoc(), SourceLoc(), TypeLoc(),
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/InstrumenterSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ bool InstrumenterBase::doTypeCheckImpl(ASTContext &Ctx, DeclContext *DC,
DiagnosticSuppression suppression(Ctx.Diags);
ErrorGatherer errorGatherer(Ctx.Diags);

TypeChecker TC(Ctx);
TypeChecker &TC = TypeChecker::createForContext(Ctx);

TC.typeCheckExpression(parsedExpr, DC);

Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/PCMacro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class Instrumenter : InstrumenterBase {

if (NB != B) {
FD->setBody(NB);
TypeChecker(Context).checkFunctionErrorHandling(FD);
TypeChecker::createForContext(Context).checkFunctionErrorHandling(FD);
}
}
} else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
Expand Down Expand Up @@ -668,7 +668,7 @@ void swift::performPCMacro(SourceFile &SF, TopLevelContext &TLC) {
BraceStmt *NewBody = I.transformBraceStmt(Body, true);
if (NewBody != Body) {
TLCD->setBody(NewBody);
TypeChecker TC(ctx);
TypeChecker &TC = TypeChecker::createForContext(ctx);
TC.checkTopLevelErrorHandling(TLCD);
TC.contextualizeTopLevelCode(TLC,
SmallVector<Decl *, 1>(1, TLCD));
Expand Down
7 changes: 4 additions & 3 deletions lib/Sema/PlaygroundTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class Instrumenter : InstrumenterBase {
BraceStmt *NB = transformBraceStmt(B);
if (NB != B) {
FD->setBody(NB);
TypeChecker(Context).checkFunctionErrorHandling(FD);
TypeChecker::createForContext(Context).checkFunctionErrorHandling(FD);
}
}
} else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
Expand Down Expand Up @@ -893,7 +893,7 @@ void swift::performPlaygroundTransform(SourceFile &SF, bool HighPerformance) {
BraceStmt *NewBody = I.transformBraceStmt(Body);
if (NewBody != Body) {
FD->setBody(NewBody);
TypeChecker(ctx).checkFunctionErrorHandling(FD);
TypeChecker::createForContext(ctx).checkFunctionErrorHandling(FD);
}
return false;
}
Expand All @@ -906,7 +906,8 @@ void swift::performPlaygroundTransform(SourceFile &SF, bool HighPerformance) {
BraceStmt *NewBody = I.transformBraceStmt(Body, true);
if (NewBody != Body) {
TLCD->setBody(NewBody);
TypeChecker(ctx).checkTopLevelErrorHandling(TLCD);
TypeChecker::createForContext(ctx)
.checkTopLevelErrorHandling(TLCD);
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1477,7 +1477,7 @@ static bool diagnoseAvailability(IdentTypeRepr *IdType,
auto componentRange = IdType->getComponentRange();
for (auto comp : componentRange) {
if (auto *typeDecl = comp->getBoundDecl()) {
// FIXME: Need to eliminate the type checker argument.
assert(ctx.getLazyResolver() && "Must have a type checker!");
TypeChecker &tc = static_cast<TypeChecker &>(*ctx.getLazyResolver());
if (diagnoseDeclAvailability(typeDecl, tc, DC, comp->getIdLoc(),
AllowPotentiallyUnavailableProtocol,
Expand Down

0 comments on commit a9315e9

Please sign in to comment.