@@ -512,35 +512,55 @@ class TypeRefinementContextBuilder : private ASTWalker {
512512 return Action::Continue ();
513513 }
514514
515- // / Constructs a placeholder TRC node that should be expanded later if the AST
516- // / associated with the given declaration is not ready to be traversed yet.
517- // / Returns true if a node was created.
518- bool buildLazyContextForDecl (Decl *D) {
519- if (!isa<PatternBindingDecl>(D))
520- return false ;
521-
522- // Check whether the current TRC is already a lazy placeholder. If it is,
523- // we should try to expand it rather than creating a new placeholder.
524- auto currentTRC = getCurrentTRC ();
525- if (currentTRC->getNeedsExpansion () && currentTRC->getDeclOrNull () == D)
526- return false ;
515+ bool shouldBuildLazyContextForDecl (Decl *D) {
516+ // Skip functions that have unparsed bodies on an initial descent to avoid
517+ // eagerly parsing bodies unnecessarily.
518+ if (auto *afd = dyn_cast<AbstractFunctionDecl>(D)) {
519+ if (afd->hasBody () && !afd->isBodySkipped () &&
520+ !afd->getBody (/* canSynthesize=*/ false ))
521+ return true ;
522+ }
527523
528524 // Pattern binding declarations may have attached property wrappers that
529525 // get expanded from macros attached to the parent declaration. We must
530- // not eagerly expand the attached property wrappers to avoid a request
531- // cycle .
526+ // not eagerly expand the attached property wrappers to avoid request
527+ // cycles .
532528 if (auto *pattern = dyn_cast<PatternBindingDecl>(D)) {
533529 if (auto firstVar = pattern->getAnchoringVarDecl (0 )) {
534- // If there's no initial value, or the init is exposed to clients, then
535- // we don't need to create any implicit TRCs for the init bodies.
536- if (!firstVar->hasInitialValue () || firstVar->isInitExposedToClients ())
537- return false ;
538-
539530 // FIXME: We could narrow this further by detecting whether there are
540531 // any macro expansions required to visit the CustomAttrs of the var.
532+ if (firstVar->hasInitialValue () && !firstVar->isInitExposedToClients ())
533+ return true ;
541534 }
542535 }
543536
537+ return false ;
538+ }
539+
540+ // / For declarations that were previously skipped prepare the AST before
541+ // / building out TRCs.
542+ void prepareDeclForLazyExpansion (Decl *D) {
543+ if (auto AFD = dyn_cast<AbstractFunctionDecl>(D)) {
544+ (void )AFD->getBody (/* canSynthesize*/ true );
545+ }
546+ }
547+
548+ // / Constructs a placeholder TRC node that should be expanded later. This is
549+ // / useful for postponing unnecessary work (and request triggers) when
550+ // / initally building out the TRC subtree under a declaration. Lazy nodes
551+ // / constructed here will be expanded by
552+ // / ExpandChildTypeRefinementContextsRequest. Returns true if a node was
553+ // / created.
554+ bool buildLazyContextForDecl (Decl *D) {
555+ // Check whether the current TRC is already a lazy placeholder. If it is,
556+ // we should try to expand it rather than creating a new placeholder.
557+ auto currentTRC = getCurrentTRC ();
558+ if (currentTRC->getNeedsExpansion () && currentTRC->getDeclOrNull () == D)
559+ return false ;
560+
561+ if (!shouldBuildLazyContextForDecl (D))
562+ return false ;
563+
544564 // If we've made it this far then we've identified a declaration that
545565 // requires lazy expansion later.
546566 auto lazyTRC = TypeRefinementContext::createForDeclImplicit (
@@ -1223,6 +1243,7 @@ class TypeRefinementContextBuilder : private ASTWalker {
12231243void TypeChecker::buildTypeRefinementContextHierarchy (SourceFile &SF) {
12241244 TypeRefinementContext *RootTRC = SF.getTypeRefinementContext ();
12251245 ASTContext &Context = SF.getASTContext ();
1246+ assert (!Context.LangOpts .DisableAvailabilityChecking );
12261247
12271248 if (!RootTRC) {
12281249 // The root type refinement context reflects the fact that all parts of
@@ -1246,28 +1267,11 @@ void TypeChecker::buildTypeRefinementContextHierarchy(SourceFile &SF) {
12461267 }
12471268}
12481269
1249- void TypeChecker::buildTypeRefinementContextHierarchyDelayed (SourceFile &SF, AbstractFunctionDecl *AFD) {
1250- // If there's no TRC for the file, we likely don't want this one either.
1251- // RootTRC is not set when availability checking is disabled.
1252- TypeRefinementContext *RootTRC = SF.getTypeRefinementContext ();
1253- if (!RootTRC)
1254- return ;
1255-
1256- if (AFD->getBodyKind () != AbstractFunctionDecl::BodyKind::Unparsed)
1257- return ;
1258-
1259- // Parse the function body.
1260- AFD->getBody (/* canSynthesize=*/ true );
1261-
1262- // Build the refinement context for the function body.
1263- ASTContext &Context = SF.getASTContext ();
1264- auto LocalTRC = RootTRC->findMostRefinedSubContext (AFD->getLoc (), Context);
1265- TypeRefinementContextBuilder Builder (LocalTRC, Context);
1266- Builder.build (AFD);
1267- }
1268-
12691270TypeRefinementContext *
12701271TypeChecker::getOrBuildTypeRefinementContext (SourceFile *SF) {
1272+ if (SF->getASTContext ().LangOpts .DisableAvailabilityChecking )
1273+ return nullptr ;
1274+
12711275 TypeRefinementContext *TRC = SF->getTypeRefinementContext ();
12721276 if (!TRC) {
12731277 buildTypeRefinementContextHierarchy (*SF);
@@ -1284,6 +1288,7 @@ ExpandChildTypeRefinementContextsRequest::evaluate(
12841288 if (auto decl = parentTRC->getDeclOrNull ()) {
12851289 ASTContext &ctx = decl->getASTContext ();
12861290 TypeRefinementContextBuilder builder (parentTRC, ctx);
1291+ builder.prepareDeclForLazyExpansion (decl);
12871292 builder.build (decl);
12881293 }
12891294 return parentTRC->Children ;
@@ -1338,11 +1343,13 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
13381343
13391344 if (SF && loc.isValid ()) {
13401345 TypeRefinementContext *rootTRC = getOrBuildTypeRefinementContext (SF);
1341- TypeRefinementContext *TRC =
1342- rootTRC->findMostRefinedSubContext (loc, Context);
1343- OverApproximateContext.constrainWith (TRC->getAvailabilityInfo ());
1344- if (MostRefined) {
1345- *MostRefined = TRC;
1346+ if (rootTRC) {
1347+ TypeRefinementContext *TRC =
1348+ rootTRC->findMostRefinedSubContext (loc, Context);
1349+ OverApproximateContext.constrainWith (TRC->getAvailabilityInfo ());
1350+ if (MostRefined) {
1351+ *MostRefined = TRC;
1352+ }
13461353 }
13471354 }
13481355
0 commit comments