Skip to content

Commit 599e07e

Browse files
committed
[Type checker] Keep the type checker alive as long as the ASTContext is.
It is possible for the SIL optimizers, IRGen, etc. to request information from the AST that only the type checker can provide, but the type checker is typically torn down after the “type checking” phase. This can lead to various crashes late in the compilation cycle. Keep the type checker instance around as long as the ASTContext is alive or until someone asks for it to be destroyed. Fixes SR-285 / rdar://problem/23677338.
1 parent 4f4167b commit 599e07e

16 files changed

+147
-173
lines changed

include/swift/AST/ASTContext.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,35 @@ class ASTContext final {
400400
/// Set a new stats reporter.
401401
void setStatsReporter(UnifiedStatsReporter *stats);
402402

403+
/// Creates a new lazy resolver by passing the ASTContext and the other
404+
/// given arguments to a newly-allocated instance of \c ResolverType.
405+
///
406+
/// \returns true if a new lazy resolver was created, false if there was
407+
/// already a lazy resolver registered.
408+
template<typename ResolverType, typename ... Args>
409+
bool createLazyResolverIfMissing(Args && ...args) {
410+
if (getLazyResolver())
411+
return false;
412+
413+
setLazyResolver(new ResolverType(*this, std::forward<Args>(args)...));
414+
return true;
415+
}
416+
417+
/// Remove the lazy resolver, if there is one.
418+
///
419+
/// FIXME: We probably don't ever want to do this.
420+
void removeLazyResolver() {
421+
setLazyResolver(nullptr);
422+
}
423+
403424
/// Retrieve the lazy resolver for this context.
404425
LazyResolver *getLazyResolver() const;
405426

427+
private:
406428
/// Set the lazy resolver for this context.
407429
void setLazyResolver(LazyResolver *resolver);
408430

431+
public:
409432
/// Add a lazy parser for resolving members later.
410433
void addLazyParser(LazyMemberParser *parser);
411434

include/swift/Sema/IDETypeChecking.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace swift {
3030
class ExtensionDecl;
3131
class ProtocolDecl;
3232
class Type;
33+
class TypeChecker;
3334
class DeclContext;
3435
class ConcreteDeclRef;
3536
class ValueDecl;
@@ -123,11 +124,11 @@ namespace swift {
123124
/// \returns true on success, false on error.
124125
bool typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD);
125126

126-
/// A unique_ptr for LazyResolver that can perform additional cleanup.
127-
using OwnedResolver = std::unique_ptr<LazyResolver, void(*)(LazyResolver*)>;
128-
129-
/// Creates a lazy type resolver for use in lookups.
130-
OwnedResolver createLazyResolver(ASTContext &Ctx);
127+
/// Creates a type checker instance on the given AST context, if it
128+
/// doesn't already have one.
129+
///
130+
/// \returns a reference to the type checker instance.
131+
TypeChecker &createTypeChecker(ASTContext &Ctx);
131132

132133
struct ExtensionInfo {
133134
// The extension with the declarations to apply.

lib/AST/ASTContext.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,8 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
428428
ASTContext::Implementation::Implementation()
429429
: IdentifierTable(Allocator), TheSyntaxArena(new SyntaxArena()) {}
430430
ASTContext::Implementation::~Implementation() {
431+
delete Resolver;
432+
431433
for (auto &cleanup : Cleanups)
432434
cleanup();
433435
}
@@ -579,13 +581,10 @@ LazyResolver *ASTContext::getLazyResolver() const {
579581

580582
/// Set the lazy resolver for this context.
581583
void ASTContext::setLazyResolver(LazyResolver *resolver) {
582-
if (resolver) {
583-
assert(getImpl().Resolver == nullptr && "already have a resolver");
584-
getImpl().Resolver = resolver;
585-
} else {
586-
assert(getImpl().Resolver != nullptr && "no resolver to remove");
587-
getImpl().Resolver = resolver;
588-
}
584+
if (auto existing = getImpl().Resolver)
585+
delete existing;
586+
587+
getImpl().Resolver = resolver;
589588
}
590589

591590
void ASTContext::addLazyParser(LazyMemberParser *lazyParser) {

lib/Frontend/Frontend.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
849849
TheSILModule ? &SILContext : nullptr, &PersistentState,
850850
DelayedParseCB);
851851

852-
if (mainIsPrimary) {
852+
if (mainIsPrimary && (Done || CurTUElem < MainFile.Decls.size())) {
853853
switch (LimitStage) {
854854
case SourceFile::Parsing:
855855
case SourceFile::Parsed:

lib/IDE/CodeCompletion.cpp

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ static bool hasTrivialTrailingClosure(const FuncDecl *FD,
15801580
class CompletionLookup final : public swift::VisibleDeclConsumer {
15811581
CodeCompletionResultSink &Sink;
15821582
ASTContext &Ctx;
1583-
OwnedResolver TypeResolver;
1583+
LazyResolver *TypeResolver = nullptr;
15841584
const DeclContext *CurrDeclContext;
15851585
ClangImporter *Importer;
15861586
CodeCompletionContext *CompletionContext;
@@ -1723,11 +1723,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
17231723
ASTContext &Ctx,
17241724
const DeclContext *CurrDeclContext,
17251725
CodeCompletionContext *CompletionContext = nullptr)
1726-
: Sink(Sink), Ctx(Ctx),
1727-
TypeResolver(createLazyResolver(Ctx)), CurrDeclContext(CurrDeclContext),
1726+
: Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
17281727
Importer(static_cast<ClangImporter *>(CurrDeclContext->getASTContext().
17291728
getClangModuleLoader())),
17301729
CompletionContext(CompletionContext) {
1730+
(void)createTypeChecker(Ctx);
1731+
TypeResolver = Ctx.getLazyResolver();
17311732

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

1740-
void discardTypeResolver() {
1741-
TypeResolver.reset();
1742-
}
1743-
17441741
void setHaveDot(SourceLoc DotLoc) {
17451742
HaveDot = true;
17461743
this->DotLoc = DotLoc;
@@ -2095,7 +2092,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20952092
if (Conformance && Conformance->isConcrete()) {
20962093
return Conformance->getConcrete()
20972094
->getTypeWitness(const_cast<AssociatedTypeDecl *>(ATD),
2098-
TypeResolver.get());
2095+
nullptr);
20992096
}
21002097
}
21012098
}
@@ -2624,7 +2621,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26242621
SmallVector<ValueDecl *, 16> initializers;
26252622
if (CurrDeclContext->lookupQualified(type, DeclBaseName::createConstructor(),
26262623
NL_QualifiedDefault,
2627-
TypeResolver.get(), initializers)) {
2624+
TypeResolver, initializers)) {
26282625
for (auto *init : initializers) {
26292626
if (shouldHideDeclFromCompletionResults(init))
26302627
continue;
@@ -3121,7 +3118,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31213118
if (isIUO) {
31223119
if (Type Unwrapped = ExprType->getOptionalObjectType()) {
31233120
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
3124-
TypeResolver.get(), IncludeInstanceMembers);
3121+
TypeResolver, IncludeInstanceMembers);
31253122
return true;
31263123
}
31273124
assert(IsUnwrappedOptional && "IUOs should be optional if not bound/forced");
@@ -3141,7 +3138,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31413138
CodeCompletionResult::MaxNumBytesToErase) {
31423139
if (!tryTupleExprCompletions(Unwrapped)) {
31433140
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
3144-
TypeResolver.get(),
3141+
TypeResolver,
31453142
IncludeInstanceMembers);
31463143
}
31473144
}
@@ -3181,7 +3178,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31813178
tryUnwrappedCompletions(ExprType, isIUO);
31823179

31833180
lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext,
3184-
TypeResolver.get(), IncludeInstanceMembers);
3181+
TypeResolver, IncludeInstanceMembers);
31853182
}
31863183

31873184
template <typename T>
@@ -3690,7 +3687,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
36903687
Kind = LookupKind::ValueInDeclContext;
36913688
NeedLeadingDot = false;
36923689
FilteredDeclConsumer Consumer(*this, Filter);
3693-
lookupVisibleDecls(Consumer, CurrDeclContext, TypeResolver.get(),
3690+
lookupVisibleDecls(Consumer, CurrDeclContext, TypeResolver,
36943691
/*IncludeTopLevel=*/IncludeTopLevel, Loc);
36953692
if (RequestCache)
36963693
RequestedCachedResults = RequestedResultsTy::toplevelResults();
@@ -3823,7 +3820,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
38233820
llvm::SaveAndRestore<Type> SaveType(ExprType, baseType);
38243821
llvm::SaveAndRestore<bool> SaveUnresolved(IsUnresolvedMember, true);
38253822
lookupVisibleMemberDecls(consumer, baseType, CurrDeclContext,
3826-
TypeResolver.get(),
3823+
TypeResolver,
38273824
/*includeInstanceMembers=*/false);
38283825
}
38293826

@@ -3989,7 +3986,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39893986
NeedLeadingDot = !HaveDot;
39903987
Type MetaBase = MetatypeType::get(BaseType);
39913988
lookupVisibleMemberDecls(*this, MetaBase,
3992-
CurrDeclContext, TypeResolver.get(),
3989+
CurrDeclContext, TypeResolver,
39933990
IncludeInstanceMembers);
39943991
addKeyword("Type", MetaBase);
39953992
}
@@ -4053,7 +4050,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
40534050

40544051
void getTypeCompletionsInDeclContext(SourceLoc Loc) {
40554052
Kind = LookupKind::TypeInDeclContext;
4056-
lookupVisibleDecls(*this, CurrDeclContext, TypeResolver.get(),
4053+
lookupVisibleDecls(*this, CurrDeclContext, TypeResolver,
40574054
/*IncludeTopLevel=*/false, Loc);
40584055

40594056
RequestedCachedResults =
@@ -4088,8 +4085,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
40884085

40894086
class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
40904087
CodeCompletionResultSink &Sink;
4091-
OwnedResolver TypeResolver;
40924088
const DeclContext *CurrDeclContext;
4089+
LazyResolver *TypeResolver;
40934090
SmallVectorImpl<StringRef> &ParsedKeywords;
40944091

40954092
bool hasFuncIntroducer = false;
@@ -4104,8 +4101,11 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41044101
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
41054102
const DeclContext *CurrDeclContext,
41064103
SmallVectorImpl<StringRef> &ParsedKeywords)
4107-
: Sink(Sink), TypeResolver(createLazyResolver(Ctx)),
4104+
: Sink(Sink),
41084105
CurrDeclContext(CurrDeclContext), ParsedKeywords(ParsedKeywords) {
4106+
(void)createTypeChecker(Ctx);
4107+
TypeResolver = Ctx.getLazyResolver();
4108+
41094109
hasFuncIntroducer = isKeywordSpecified("func");
41104110
hasVarIntroducer = isKeywordSpecified("var") ||
41114111
isKeywordSpecified("let");
@@ -4377,7 +4377,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
43774377
Type CurrTy = CurrDeclContext->getDeclaredTypeInContext();
43784378
if (CurrTy && !CurrTy->is<ErrorType>()) {
43794379
lookupVisibleMemberDecls(*this, CurrTy, CurrDeclContext,
4380-
TypeResolver.get(),
4380+
TypeResolver,
43814381
/*includeInstanceMembers=*/false);
43824382
addDesignatedInitializers(CurrTy);
43834383
addAssociatedTypes(CurrTy);
@@ -5521,7 +5521,6 @@ void CodeCompletionCallbacksImpl::doneParsing() {
55215521
}
55225522

55235523
case CompletionKind::NominalMemberBeginning: {
5524-
Lookup.discardTypeResolver();
55255524
CompletionOverrideLookup OverrideLookup(CompletionContext.getResultSink(),
55265525
P.Context, CurDeclContext,
55275526
ParsedKeywords);
@@ -5683,15 +5682,12 @@ void CodeCompletionCallbacksImpl::doneParsing() {
56835682
};
56845683

56855684
if (Request.TheModule) {
5686-
Lookup.discardTypeResolver();
5687-
56885685
// FIXME: actually check imports.
56895686
const_cast<ModuleDecl*>(Request.TheModule)
56905687
->forAllVisibleModules({}, handleImport);
56915688
} else {
56925689
// Add results from current module.
56935690
Lookup.getToplevelCompletions(Request.OnlyTypes);
5694-
Lookup.discardTypeResolver();
56955691

56965692
// Add results for all imported modules.
56975693
SmallVector<ModuleDecl::ImportedModule, 4> Imports;

lib/Sema/CSGen.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,13 +3664,7 @@ bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
36643664
BaseTy->hasUnboundGenericType())
36653665
return true;
36663666

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

36753669
ConstraintSystemOptions Options;
36763670
ConstraintSystem CS(*TC, &DC, Options);
@@ -3696,14 +3690,9 @@ bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
36963690
static bool canSatisfy(Type type1, Type type2, bool openArchetypes,
36973691
ConstraintKind kind, DeclContext *dc) {
36983692
std::unique_ptr<TypeChecker> CreatedTC;
3699-
// If the current ASTContext has no type checker, create one for it.
3700-
auto *TC = static_cast<TypeChecker*>(dc->getASTContext().getLazyResolver());
3701-
if (!TC) {
3702-
CreatedTC.reset(new TypeChecker(dc->getASTContext()));
3703-
TC = CreatedTC.get();
3704-
}
3705-
return TC->typesSatisfyConstraint(type1, type2, openArchetypes, kind, dc,
3706-
/*unwrappedIUO=*/nullptr);
3693+
auto &TC = TypeChecker::createForContext(dc->getASTContext());
3694+
return TC.typesSatisfyConstraint(type1, type2, openArchetypes, kind, dc,
3695+
/*unwrappedIUO=*/nullptr);
37073696
}
37083697

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

37753760
// Look up all members of BaseTy with the given Name.
37763761
MemberLookupResult LookupResult = CS.performMemberLookup(

lib/Sema/DebuggerTestingTransform.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class DebuggerTestingTransform : public ASTWalker {
215215
CheckExpectExpr->setThrows(false);
216216

217217
// Create the closure.
218-
TypeChecker TC{Ctx};
218+
TypeChecker &TC = TypeChecker::createForContext(Ctx);
219219
auto *Params = ParameterList::createEmpty(Ctx);
220220
auto *Closure = new (Ctx)
221221
ClosureExpr(Params, SourceLoc(), SourceLoc(), SourceLoc(), TypeLoc(),

lib/Sema/InstrumenterSupport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ bool InstrumenterBase::doTypeCheckImpl(ASTContext &Ctx, DeclContext *DC,
8181
DiagnosticSuppression suppression(Ctx.Diags);
8282
ErrorGatherer errorGatherer(Ctx.Diags);
8383

84-
TypeChecker TC(Ctx);
84+
TypeChecker &TC = TypeChecker::createForContext(Ctx);
8585

8686
TC.typeCheckExpression(parsedExpr, DC);
8787

lib/Sema/PCMacro.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ class Instrumenter : InstrumenterBase {
322322

323323
if (NB != B) {
324324
FD->setBody(NB);
325-
TypeChecker(Context).checkFunctionErrorHandling(FD);
325+
TypeChecker::createForContext(Context).checkFunctionErrorHandling(FD);
326326
}
327327
}
328328
} else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
@@ -668,7 +668,7 @@ void swift::performPCMacro(SourceFile &SF, TopLevelContext &TLC) {
668668
BraceStmt *NewBody = I.transformBraceStmt(Body, true);
669669
if (NewBody != Body) {
670670
TLCD->setBody(NewBody);
671-
TypeChecker TC(ctx);
671+
TypeChecker &TC = TypeChecker::createForContext(ctx);
672672
TC.checkTopLevelErrorHandling(TLCD);
673673
TC.contextualizeTopLevelCode(TLC,
674674
SmallVector<Decl *, 1>(1, TLCD));

lib/Sema/PlaygroundTransform.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ class Instrumenter : InstrumenterBase {
280280
BraceStmt *NB = transformBraceStmt(B);
281281
if (NB != B) {
282282
FD->setBody(NB);
283-
TypeChecker(Context).checkFunctionErrorHandling(FD);
283+
TypeChecker::createForContext(Context).checkFunctionErrorHandling(FD);
284284
}
285285
}
286286
} else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
@@ -893,7 +893,7 @@ void swift::performPlaygroundTransform(SourceFile &SF, bool HighPerformance) {
893893
BraceStmt *NewBody = I.transformBraceStmt(Body);
894894
if (NewBody != Body) {
895895
FD->setBody(NewBody);
896-
TypeChecker(ctx).checkFunctionErrorHandling(FD);
896+
TypeChecker::createForContext(ctx).checkFunctionErrorHandling(FD);
897897
}
898898
return false;
899899
}
@@ -906,7 +906,8 @@ void swift::performPlaygroundTransform(SourceFile &SF, bool HighPerformance) {
906906
BraceStmt *NewBody = I.transformBraceStmt(Body, true);
907907
if (NewBody != Body) {
908908
TLCD->setBody(NewBody);
909-
TypeChecker(ctx).checkTopLevelErrorHandling(TLCD);
909+
TypeChecker::createForContext(ctx)
910+
.checkTopLevelErrorHandling(TLCD);
910911
}
911912
return false;
912913
}

0 commit comments

Comments
 (0)