@@ -472,6 +472,17 @@ class TypeRefinementContextBuilder : private ASTWalker {
472
472
PreWalkAction walkToDeclPre (Decl *D) override {
473
473
PrettyStackTraceDecl trace (stackTraceAction (), D);
474
474
475
+ // Implicit decls don't have source locations so they cannot have a TRC.
476
+ if (D->isImplicit ())
477
+ return Action::Continue ();
478
+
479
+ // The AST of this decl may not be ready to traverse yet if it hasn't been
480
+ // full typechecked. If that's the case, we leave a placeholder node in the
481
+ // tree to indicate that the subtree should be expanded lazily when it
482
+ // needs to be traversed.
483
+ if (buildLazyContextForDecl (D))
484
+ return Action::SkipChildren ();
485
+
475
486
// Adds in a TRC that covers the entire declaration.
476
487
if (auto DeclTRC = getNewContextForSignatureOfDecl (D)) {
477
488
pushContext (DeclTRC, D);
@@ -497,6 +508,44 @@ class TypeRefinementContextBuilder : private ASTWalker {
497
508
return Action::Continue ();
498
509
}
499
510
511
+ // / Constructs a placeholder TRC node that should be expanded later if the AST
512
+ // / associated with the given declaration is not ready to be traversed yet.
513
+ // / Returns true if a node was created.
514
+ bool buildLazyContextForDecl (Decl *D) {
515
+ if (!isa<PatternBindingDecl>(D))
516
+ return false ;
517
+
518
+ // Check whether the current TRC is already a lazy placeholder. If it is,
519
+ // we should try to expand it rather than creating a new placeholder.
520
+ auto currentTRC = getCurrentTRC ();
521
+ if (currentTRC->getNeedsExpansion () && currentTRC->getDeclOrNull () == D)
522
+ return false ;
523
+
524
+ // Pattern binding declarations may have attached property wrappers that
525
+ // get expanded from macros attached to the parent declaration. We must
526
+ // not eagerly expand the attached property wrappers to avoid a request
527
+ // cycle.
528
+ if (auto *pattern = dyn_cast<PatternBindingDecl>(D)) {
529
+ if (auto firstVar = pattern->getAnchoringVarDecl (0 )) {
530
+ // If there's no initial value, or the init is exposed to clients, then
531
+ // we don't need to create any implicit TRCs for the init bodies.
532
+ if (!firstVar->hasInitialValue () || firstVar->isInitExposedToClients ())
533
+ return false ;
534
+
535
+ // FIXME: We could narrow this further by detecting whether there are
536
+ // any macro expansions required to visit the CustomAttrs of the var.
537
+ }
538
+ }
539
+
540
+ // If we've made it this far then we've identified a declaration that
541
+ // requires lazy expansion later.
542
+ auto lazyTRC = TypeRefinementContext::createForDeclImplicit (
543
+ Context, D, currentTRC, currentTRC->getAvailabilityInfo (),
544
+ refinementSourceRangeForDecl (D));
545
+ lazyTRC->setNeedsExpansion (true );
546
+ return true ;
547
+ }
548
+
500
549
// / Returns a new context to be introduced for the declaration, or nullptr
501
550
// / if no new context should be introduced.
502
551
TypeRefinementContext *getNewContextForSignatureOfDecl (Decl *D) {
@@ -519,10 +568,6 @@ class TypeRefinementContextBuilder : private ASTWalker {
519
568
return nullptr ;
520
569
}
521
570
522
- // Ignore implicit declarations (mainly skips over `DeferStmt` functions).
523
- if (D->isImplicit ())
524
- return nullptr ;
525
-
526
571
// Declarations with an explicit availability attribute always get a TRC.
527
572
if (hasActiveAvailableAttribute (D, Context)) {
528
573
AvailabilityContext DeclaredAvailability =
@@ -539,17 +584,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
539
584
// internal property in a public struct can be effectively less available
540
585
// than the containing struct decl because the internal property will only
541
586
// be accessed by code running at the deployment target or later.
542
- //
543
- // For declarations that have their child construction delayed, always
544
- // create this implicit declaration context. It will be used to trigger
545
- // lazy creation of the child TRCs.
546
587
AvailabilityContext CurrentAvailability =
547
588
getCurrentTRC ()->getAvailabilityInfo ();
548
589
AvailabilityContext EffectiveAvailability =
549
590
getEffectiveAvailabilityForDeclSignature (D, CurrentAvailability);
550
- if ((isa<PatternBindingDecl>(D) &&
551
- refinementSourceRangeForDecl (D).isValid ()) ||
552
- CurrentAvailability.isSupersetOf (EffectiveAvailability))
591
+ if (CurrentAvailability.isSupersetOf (EffectiveAvailability))
553
592
return TypeRefinementContext::createForDeclImplicit (
554
593
Context, D, getCurrentTRC (), EffectiveAvailability,
555
594
refinementSourceRangeForDecl (D));
@@ -732,6 +771,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
732
771
}
733
772
return ;
734
773
}
774
+
775
+ if (auto pattern = dyn_cast<PatternBindingDecl>(D)) {
776
+ buildContextsForPatternBindingDecl (pattern);
777
+ return ;
778
+ }
735
779
}
736
780
737
781
PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
@@ -1208,7 +1252,7 @@ void TypeChecker::buildTypeRefinementContextHierarchyDelayed(SourceFile &SF, Abs
1208
1252
1209
1253
// Build the refinement context for the function body.
1210
1254
ASTContext &Context = SF.getASTContext ();
1211
- auto LocalTRC = RootTRC->findMostRefinedSubContext (AFD->getLoc (), Context. SourceMgr );
1255
+ auto LocalTRC = RootTRC->findMostRefinedSubContext (AFD->getLoc (), Context);
1212
1256
TypeRefinementContextBuilder Builder (LocalTRC, Context);
1213
1257
Builder.build (AFD);
1214
1258
}
@@ -1224,23 +1268,16 @@ TypeChecker::getOrBuildTypeRefinementContext(SourceFile *SF) {
1224
1268
return TRC;
1225
1269
}
1226
1270
1227
- bool ExpandChildTypeRefinementContextsRequest::evaluate (
1228
- Evaluator &evaluator, Decl *decl, TypeRefinementContext *parentTRC
1229
- ) const {
1230
- // If the parent TRC is already contained by the deployment target, there's
1231
- // nothing more to do.
1232
- ASTContext &ctx = decl->getASTContext ();
1233
- if (computeContainedByDeploymentTarget (parentTRC, ctx))
1234
- return false ;
1235
-
1236
- // Pattern binding declarations can have children corresponding to property
1237
- // wrappers and the initial values provided in each pattern binding entry.
1238
- if (auto *binding = dyn_cast<PatternBindingDecl>(decl)) {
1271
+ std::vector<TypeRefinementContext *>
1272
+ ExpandChildTypeRefinementContextsRequest::evaluate (
1273
+ Evaluator &evaluator, TypeRefinementContext *parentTRC) const {
1274
+ assert (parentTRC->getNeedsExpansion ());
1275
+ if (auto decl = parentTRC->getDeclOrNull ()) {
1276
+ ASTContext &ctx = decl->getASTContext ();
1239
1277
TypeRefinementContextBuilder builder (parentTRC, ctx);
1240
- builder.buildContextsForPatternBindingDecl (binding );
1278
+ builder.build (decl );
1241
1279
}
1242
-
1243
- return false ;
1280
+ return parentTRC->Children ;
1244
1281
}
1245
1282
1246
1283
AvailabilityContext
@@ -1293,7 +1330,7 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
1293
1330
if (SF && loc.isValid ()) {
1294
1331
TypeRefinementContext *rootTRC = getOrBuildTypeRefinementContext (SF);
1295
1332
TypeRefinementContext *TRC =
1296
- rootTRC->findMostRefinedSubContext (loc, Context. SourceMgr );
1333
+ rootTRC->findMostRefinedSubContext (loc, Context);
1297
1334
OverApproximateContext.constrainWith (TRC->getAvailabilityInfo ());
1298
1335
if (MostRefined) {
1299
1336
*MostRefined = TRC;
0 commit comments