@@ -472,6 +472,17 @@ class TypeRefinementContextBuilder : private ASTWalker {
472472 PreWalkAction walkToDeclPre (Decl *D) override {
473473 PrettyStackTraceDecl trace (stackTraceAction (), D);
474474
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+
475486 // Adds in a TRC that covers the entire declaration.
476487 if (auto DeclTRC = getNewContextForSignatureOfDecl (D)) {
477488 pushContext (DeclTRC, D);
@@ -497,6 +508,44 @@ class TypeRefinementContextBuilder : private ASTWalker {
497508 return Action::Continue ();
498509 }
499510
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+
500549 // / Returns a new context to be introduced for the declaration, or nullptr
501550 // / if no new context should be introduced.
502551 TypeRefinementContext *getNewContextForSignatureOfDecl (Decl *D) {
@@ -519,10 +568,6 @@ class TypeRefinementContextBuilder : private ASTWalker {
519568 return nullptr ;
520569 }
521570
522- // Ignore implicit declarations (mainly skips over `DeferStmt` functions).
523- if (D->isImplicit ())
524- return nullptr ;
525-
526571 // Declarations with an explicit availability attribute always get a TRC.
527572 if (hasActiveAvailableAttribute (D, Context)) {
528573 AvailabilityContext DeclaredAvailability =
@@ -539,17 +584,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
539584 // internal property in a public struct can be effectively less available
540585 // than the containing struct decl because the internal property will only
541586 // 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.
546587 AvailabilityContext CurrentAvailability =
547588 getCurrentTRC ()->getAvailabilityInfo ();
548589 AvailabilityContext EffectiveAvailability =
549590 getEffectiveAvailabilityForDeclSignature (D, CurrentAvailability);
550- if ((isa<PatternBindingDecl>(D) &&
551- refinementSourceRangeForDecl (D).isValid ()) ||
552- CurrentAvailability.isSupersetOf (EffectiveAvailability))
591+ if (CurrentAvailability.isSupersetOf (EffectiveAvailability))
553592 return TypeRefinementContext::createForDeclImplicit (
554593 Context, D, getCurrentTRC (), EffectiveAvailability,
555594 refinementSourceRangeForDecl (D));
@@ -732,6 +771,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
732771 }
733772 return ;
734773 }
774+
775+ if (auto pattern = dyn_cast<PatternBindingDecl>(D)) {
776+ buildContextsForPatternBindingDecl (pattern);
777+ return ;
778+ }
735779 }
736780
737781 PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
@@ -1208,7 +1252,7 @@ void TypeChecker::buildTypeRefinementContextHierarchyDelayed(SourceFile &SF, Abs
12081252
12091253 // Build the refinement context for the function body.
12101254 ASTContext &Context = SF.getASTContext ();
1211- auto LocalTRC = RootTRC->findMostRefinedSubContext (AFD->getLoc (), Context. SourceMgr );
1255+ auto LocalTRC = RootTRC->findMostRefinedSubContext (AFD->getLoc (), Context);
12121256 TypeRefinementContextBuilder Builder (LocalTRC, Context);
12131257 Builder.build (AFD);
12141258}
@@ -1224,23 +1268,16 @@ TypeChecker::getOrBuildTypeRefinementContext(SourceFile *SF) {
12241268 return TRC;
12251269}
12261270
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 ();
12391277 TypeRefinementContextBuilder builder (parentTRC, ctx);
1240- builder.buildContextsForPatternBindingDecl (binding );
1278+ builder.build (decl );
12411279 }
1242-
1243- return false ;
1280+ return parentTRC->Children ;
12441281}
12451282
12461283AvailabilityContext
@@ -1293,7 +1330,7 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
12931330 if (SF && loc.isValid ()) {
12941331 TypeRefinementContext *rootTRC = getOrBuildTypeRefinementContext (SF);
12951332 TypeRefinementContext *TRC =
1296- rootTRC->findMostRefinedSubContext (loc, Context. SourceMgr );
1333+ rootTRC->findMostRefinedSubContext (loc, Context);
12971334 OverApproximateContext.constrainWith (TRC->getAvailabilityInfo ());
12981335 if (MostRefined) {
12991336 *MostRefined = TRC;
0 commit comments