@@ -512,35 +512,55 @@ class TypeRefinementContextBuilder : private ASTWalker {
512
512
return Action::Continue ();
513
513
}
514
514
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
+ }
527
523
528
524
// Pattern binding declarations may have attached property wrappers that
529
525
// 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 .
532
528
if (auto *pattern = dyn_cast<PatternBindingDecl>(D)) {
533
529
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
-
539
530
// FIXME: We could narrow this further by detecting whether there are
540
531
// any macro expansions required to visit the CustomAttrs of the var.
532
+ if (firstVar->hasInitialValue () && !firstVar->isInitExposedToClients ())
533
+ return true ;
541
534
}
542
535
}
543
536
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
+
544
564
// If we've made it this far then we've identified a declaration that
545
565
// requires lazy expansion later.
546
566
auto lazyTRC = TypeRefinementContext::createForDeclImplicit (
@@ -1223,6 +1243,7 @@ class TypeRefinementContextBuilder : private ASTWalker {
1223
1243
void TypeChecker::buildTypeRefinementContextHierarchy (SourceFile &SF) {
1224
1244
TypeRefinementContext *RootTRC = SF.getTypeRefinementContext ();
1225
1245
ASTContext &Context = SF.getASTContext ();
1246
+ assert (!Context.LangOpts .DisableAvailabilityChecking );
1226
1247
1227
1248
if (!RootTRC) {
1228
1249
// The root type refinement context reflects the fact that all parts of
@@ -1246,28 +1267,11 @@ void TypeChecker::buildTypeRefinementContextHierarchy(SourceFile &SF) {
1246
1267
}
1247
1268
}
1248
1269
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
-
1269
1270
TypeRefinementContext *
1270
1271
TypeChecker::getOrBuildTypeRefinementContext (SourceFile *SF) {
1272
+ if (SF->getASTContext ().LangOpts .DisableAvailabilityChecking )
1273
+ return nullptr ;
1274
+
1271
1275
TypeRefinementContext *TRC = SF->getTypeRefinementContext ();
1272
1276
if (!TRC) {
1273
1277
buildTypeRefinementContextHierarchy (*SF);
@@ -1284,6 +1288,7 @@ ExpandChildTypeRefinementContextsRequest::evaluate(
1284
1288
if (auto decl = parentTRC->getDeclOrNull ()) {
1285
1289
ASTContext &ctx = decl->getASTContext ();
1286
1290
TypeRefinementContextBuilder builder (parentTRC, ctx);
1291
+ builder.prepareDeclForLazyExpansion (decl);
1287
1292
builder.build (decl);
1288
1293
}
1289
1294
return parentTRC->Children ;
@@ -1338,11 +1343,13 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
1338
1343
1339
1344
if (SF && loc.isValid ()) {
1340
1345
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
+ }
1346
1353
}
1347
1354
}
1348
1355
0 commit comments