@@ -440,6 +440,8 @@ class TypeRefinementContextBuilder : private ASTWalker {
440
440
return " building type refinement context for" ;
441
441
}
442
442
443
+ friend class swift ::ExpandChildTypeRefinementContextsRequest;
444
+
443
445
public:
444
446
TypeRefinementContextBuilder (TypeRefinementContext *TRC, ASTContext &Context)
445
447
: Context(Context) {
@@ -576,9 +578,10 @@ class TypeRefinementContextBuilder : private ASTWalker {
576
578
// pattern. The context necessary for the pattern as a whole was already
577
579
// introduced if necessary by the first var decl.
578
580
if (auto *VD = dyn_cast<VarDecl>(D)) {
579
- if (auto *PBD = VD->getParentPatternBinding ())
581
+ if (auto *PBD = VD->getParentPatternBinding ()) {
580
582
if (VD != PBD->getAnchoringVarDecl (0 ))
581
583
return nullptr ;
584
+ }
582
585
}
583
586
584
587
// Declarations with an explicit availability attribute always get a TRC.
@@ -597,11 +600,16 @@ class TypeRefinementContextBuilder : private ASTWalker {
597
600
// internal property in a public struct can be effectively less available
598
601
// than the containing struct decl because the internal property will only
599
602
// be accessed by code running at the deployment target or later.
603
+ //
604
+ // For declarations that have their child construction delayed, always
605
+ // create this implicit declaration context. It will be used to trigger
606
+ // lazy creation of the child TRCs.
600
607
AvailabilityContext CurrentAvailability =
601
608
getCurrentTRC ()->getAvailabilityInfo ();
602
609
AvailabilityContext EffectiveAvailability =
603
610
getEffectiveAvailabilityForDeclSignature (D, CurrentAvailability);
604
- if (CurrentAvailability.isSupersetOf (EffectiveAvailability))
611
+ if (isa<VarDecl>(D) ||
612
+ CurrentAvailability.isSupersetOf (EffectiveAvailability))
605
613
return TypeRefinementContext::createForDeclImplicit (
606
614
Context, D, getCurrentTRC (), EffectiveAvailability,
607
615
refinementSourceRangeForDecl (D));
@@ -709,28 +717,79 @@ class TypeRefinementContextBuilder : private ASTWalker {
709
717
return D->getSourceRange ();
710
718
}
711
719
720
+ // Creates an implicit decl TRC specifying the deployment
721
+ // target for `range` in decl `D`.
722
+ TypeRefinementContext *
723
+ createImplicitDeclContextForDeploymentTarget (Decl *D, SourceRange range){
724
+ AvailabilityContext Availability =
725
+ AvailabilityContext::forDeploymentTarget (Context);
726
+ Availability.intersectWith (getCurrentTRC ()->getAvailabilityInfo ());
727
+
728
+ return TypeRefinementContext::createForDeclImplicit (
729
+ Context, D, getCurrentTRC (), Availability, range);
730
+ }
731
+
732
+ // / Build contexts for a VarDecl with the given initializer.
733
+ void buildContextsForPatternBindingDecl (PatternBindingDecl *pattern) {
734
+ // Build contexts for each of the pattern entries.
735
+ for (unsigned index : range (pattern->getNumPatternEntries ())) {
736
+ auto var = pattern->getAnchoringVarDecl (index );
737
+ if (!var)
738
+ continue ;
739
+
740
+ // Var decls may have associated pattern binding decls or property wrappers
741
+ // with init expressions. Those expressions need to be constrained to the
742
+ // deployment target unless they are exposed to clients.
743
+ if (!var->hasInitialValue () || var->isInitExposedToClients ())
744
+ continue ;
745
+
746
+ auto *initExpr = pattern->getInit (index );
747
+ if (initExpr && !initExpr->isImplicit ()) {
748
+ assert (initExpr->getSourceRange ().isValid ());
749
+
750
+ // Create a TRC for the init written in the source. The ASTWalker
751
+ // won't visit these expressions so instead of pushing these onto the
752
+ // stack we build them directly.
753
+ auto *initTRC = createImplicitDeclContextForDeploymentTarget (
754
+ var, initExpr->getSourceRange ());
755
+ TypeRefinementContextBuilder (initTRC, Context).build (initExpr);
756
+ }
757
+ }
758
+
759
+ // Ideally any init expression would be returned by `getInit()` above.
760
+ // However, for property wrappers it doesn't get populated until
761
+ // typechecking completes (which is too late). Instead, we find the
762
+ // the property wrapper attribute and use its source range to create a
763
+ // TRC for the initializer expression.
764
+ //
765
+ // FIXME: Since we don't have an expression here, we can't build out its
766
+ // TRC. If the Expr that will eventually be created contains a closure
767
+ // expression, then it might have AST nodes that need to be refined. For
768
+ // example, property wrapper initializers that takes block arguments
769
+ // are not handled correctly because of this (rdar://77841331).
770
+ if (auto firstVar = pattern->getAnchoringVarDecl (0 )) {
771
+ if (firstVar->hasInitialValue () && !firstVar->isInitExposedToClients ()) {
772
+ for (auto *wrapper : firstVar->getAttachedPropertyWrappers ()) {
773
+ createImplicitDeclContextForDeploymentTarget (
774
+ firstVar, wrapper->getRange ());
775
+ }
776
+ }
777
+ }
778
+ }
779
+
712
780
void buildContextsForBodyOfDecl (Decl *D) {
713
781
// Are we already constrained by the deployment target? If not, adding
714
782
// new contexts won't change availability.
715
783
if (isCurrentTRCContainedByDeploymentTarget ())
716
784
return ;
717
785
718
- // A lambda that creates an implicit decl TRC specifying the deployment
719
- // target for `range` in decl `D`.
720
- auto createContext = [this ](Decl *D, SourceRange range) {
721
- AvailabilityContext Availability =
722
- AvailabilityContext::forDeploymentTarget (Context);
723
- Availability.intersectWith (getCurrentTRC ()->getAvailabilityInfo ());
724
-
725
- return TypeRefinementContext::createForDeclImplicit (
726
- Context, D, getCurrentTRC (), Availability, range);
727
- };
728
-
729
786
// Top level code always uses the deployment target.
730
787
if (auto tlcd = dyn_cast<TopLevelCodeDecl>(D)) {
731
788
if (auto bodyStmt = tlcd->getBody ()) {
732
- pushDeclBodyContext (createContext (tlcd, tlcd->getSourceRange ()), tlcd,
733
- bodyStmt);
789
+ pushDeclBodyContext (
790
+ createImplicitDeclContextForDeploymentTarget (
791
+ tlcd, tlcd->getSourceRange ()),
792
+ tlcd, bodyStmt);
734
793
}
735
794
return ;
736
795
}
@@ -741,51 +800,14 @@ class TypeRefinementContextBuilder : private ASTWalker {
741
800
if (!afd->isImplicit () &&
742
801
afd->getResilienceExpansion () != ResilienceExpansion::Minimal) {
743
802
if (auto body = afd->getBody (/* canSynthesize*/ false )) {
744
- pushDeclBodyContext (createContext (afd, afd->getBodySourceRange ()),
745
- afd, body);
803
+ pushDeclBodyContext (
804
+ createImplicitDeclContextForDeploymentTarget (
805
+ afd, afd->getBodySourceRange ()),
806
+ afd, body);
746
807
}
747
808
}
748
809
return ;
749
810
}
750
-
751
- // Var decls may have associated pattern binding decls or property wrappers
752
- // with init expressions. Those expressions need to be constrained to the
753
- // deployment target unless they are exposed to clients.
754
- if (auto vd = dyn_cast<VarDecl>(D)) {
755
- if (!vd->hasInitialValue () || vd->isInitExposedToClients ())
756
- return ;
757
-
758
- if (auto *pbd = vd->getParentPatternBinding ()) {
759
- int idx = pbd->getPatternEntryIndexForVarDecl (vd);
760
- auto *initExpr = pbd->getInit (idx);
761
- if (initExpr && !initExpr->isImplicit ()) {
762
- assert (initExpr->getSourceRange ().isValid ());
763
-
764
- // Create a TRC for the init written in the source. The ASTWalker
765
- // won't visit these expressions so instead of pushing these onto the
766
- // stack we build them directly.
767
- auto *initTRC = createContext (vd, initExpr->getSourceRange ());
768
- TypeRefinementContextBuilder (initTRC, Context).build (initExpr);
769
- }
770
-
771
- // Ideally any init expression would be returned by `getInit()` above.
772
- // However, for property wrappers it doesn't get populated until
773
- // typechecking completes (which is too late). Instead, we find the
774
- // the property wrapper attribute and use its source range to create a
775
- // TRC for the initializer expression.
776
- //
777
- // FIXME: Since we don't have an expression here, we can't build out its
778
- // TRC. If the Expr that will eventually be created contains a closure
779
- // expression, then it might have AST nodes that need to be refined. For
780
- // example, property wrapper initializers that takes block arguments
781
- // are not handled correctly because of this (rdar://77841331).
782
- for (auto *wrapper : vd->getAttachedPropertyWrappers ()) {
783
- createContext (vd, wrapper->getRange ());
784
- }
785
- }
786
-
787
- return ;
788
- }
789
811
}
790
812
791
813
PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
@@ -1277,6 +1299,36 @@ TypeChecker::getOrBuildTypeRefinementContext(SourceFile *SF) {
1277
1299
return TRC;
1278
1300
}
1279
1301
1302
+ bool ExpandChildTypeRefinementContextsRequest::evaluate (
1303
+ Evaluator &evaluator, Decl *decl, TypeRefinementContext *parentTRC
1304
+ ) const {
1305
+ // If the parent TRC is already contained by the deployment target, there's
1306
+ // nothing more to do.
1307
+ ASTContext &ctx = decl->getASTContext ();
1308
+ if (computeContainedByDeploymentTarget (parentTRC, ctx))
1309
+ return false ;
1310
+
1311
+ // Variables can have children corresponding to property wrappers and
1312
+ // the initial values provided in each pattern binding entry.
1313
+ if (auto var = dyn_cast<VarDecl>(decl)) {
1314
+ if (auto *pattern = var->getParentPatternBinding ()) {
1315
+ // Only do this for the first variable in the pattern binding declaration.
1316
+ auto anchorVar = pattern->getAnchoringVarDecl (0 );
1317
+ if (anchorVar != var) {
1318
+ return evaluateOrDefault (
1319
+ evaluator,
1320
+ ExpandChildTypeRefinementContextsRequest{anchorVar, parentTRC},
1321
+ false );
1322
+ }
1323
+
1324
+ TypeRefinementContextBuilder builder (parentTRC, ctx);
1325
+ builder.buildContextsForPatternBindingDecl (pattern);
1326
+ }
1327
+ }
1328
+
1329
+ return false ;
1330
+ }
1331
+
1280
1332
AvailabilityContext
1281
1333
TypeChecker::overApproximateAvailabilityAtLocation (SourceLoc loc,
1282
1334
const DeclContext *DC,
0 commit comments