@@ -181,7 +181,7 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
181181 auto runningOSVersion =
182182 (Ctx.LangOpts .DisableAvailabilityChecking
183183 ? AvailabilityContext::alwaysAvailable ()
184- : TypeChecker::overApproximateAvailabilityAtLocation (D->getEndLoc (), DC));
184+ : TypeChecker::overApproximateAvailabilityAtLocation (D->getLoc (), DC));
185185 bool spi = Ctx.LangOpts .LibraryLevel == LibraryLevel::SPI;
186186 bool implicit = false ;
187187 bool deprecated = false ;
@@ -288,6 +288,27 @@ static bool hasActiveAvailableAttribute(Decl *D,
288288 return getActiveAvailableAttribute (D, AC);
289289}
290290
291+ static bool bodyIsResilienceBoundary (Decl *D) {
292+ // The declaration contains code...
293+ if (auto afd = dyn_cast<AbstractFunctionDecl>(D)) {
294+ // And it has a location so we can check it...
295+ if (!afd->isImplicit () && afd->getBodySourceRange ().isValid ()) {
296+ // And the code is within our resilience domain, so it should be
297+ // compiled with the minimum deployment target, not the minimum inlining
298+ // target.
299+ return afd->getResilienceExpansion () != ResilienceExpansion::Minimal;
300+ }
301+ }
302+
303+ return false ;
304+ }
305+
306+ static bool computeContainedByDeploymentTarget (TypeRefinementContext *TRC,
307+ ASTContext &ctx) {
308+ return TRC->getAvailabilityInfo ()
309+ .isContainedIn (AvailabilityContext::forDeploymentTarget (ctx));
310+ }
311+
291312namespace {
292313
293314// / A class to walk the AST to build the type refinement context hierarchy.
@@ -302,6 +323,8 @@ class TypeRefinementContextBuilder : private ASTWalker {
302323 // / indicating that custom logic elsewhere will handle removing
303324 // / the context when needed.
304325 ParentTy ScopeNode;
326+
327+ bool ContainedByDeploymentTarget;
305328 };
306329
307330 std::vector<ContextInfo> ContextStack;
@@ -318,10 +341,24 @@ class TypeRefinementContextBuilder : private ASTWalker {
318341 return ContextStack.back ().TRC ;
319342 }
320343
344+ bool isCurrentTRCContainedByDeploymentTarget () {
345+ return ContextStack.back ().ContainedByDeploymentTarget ;
346+ }
347+
321348 void pushContext (TypeRefinementContext *TRC, ParentTy PopAfterNode) {
322349 ContextInfo Info;
323350 Info.TRC = TRC;
324351 Info.ScopeNode = PopAfterNode;
352+
353+ if (!ContextStack.empty () && isCurrentTRCContainedByDeploymentTarget ()) {
354+ assert (computeContainedByDeploymentTarget (TRC, Context) &&
355+ " incorrectly skipping computeContainedByDeploymentTarget()" );
356+ Info.ContainedByDeploymentTarget = true ;
357+ } else {
358+ Info.ContainedByDeploymentTarget =
359+ computeContainedByDeploymentTarget (TRC, Context);
360+ }
361+
325362 ContextStack.push_back (Info);
326363 }
327364
@@ -367,11 +404,16 @@ class TypeRefinementContextBuilder : private ASTWalker {
367404 pushContext (DeclTRC, D);
368405 }
369406
407+ // Adds in a TRC that covers only the body of the declaration.
408+ if (auto BodyTRC = getNewContextForBodyOfDecl (D)) {
409+ pushContext (BodyTRC, D);
410+ }
411+
370412 return true ;
371413 }
372414
373415 bool walkToDeclPost (Decl *D) override {
374- // As seen above, we could have up to two TRCs in the stack for a single
416+ // As seen above, we could have up to three TRCs in the stack for a single
375417 // declaration.
376418 while (ContextStack.back ().ScopeNode .getAsDecl () == D) {
377419 ContextStack.pop_back ();
@@ -510,6 +552,39 @@ class TypeRefinementContextBuilder : private ASTWalker {
510552 return D->getSourceRange ();
511553 }
512554
555+ TypeRefinementContext *getNewContextForBodyOfDecl (Decl *D) {
556+ if (bodyIntroducesNewContext (D))
557+ return buildBodyRefinementContext (D);
558+
559+ return nullptr ;
560+ }
561+
562+ bool bodyIntroducesNewContext (Decl *D) {
563+ // Are we already effectively in a resilience boundary? If not, adding one
564+ // wouldn't change availability.
565+ if (isCurrentTRCContainedByDeploymentTarget ())
566+ return false ;
567+
568+ // If we're in a function, is its body a resilience boundary?
569+ if (auto afd = dyn_cast<AbstractFunctionDecl>(D))
570+ return bodyIsResilienceBoundary (afd);
571+
572+ return false ;
573+ }
574+
575+ TypeRefinementContext *buildBodyRefinementContext (Decl *D) {
576+ auto afd = cast<AbstractFunctionDecl>(D);
577+ SourceRange range = afd->getBodySourceRange ();
578+
579+ AvailabilityContext DeploymentTargetInfo =
580+ AvailabilityContext::forDeploymentTarget (Context);
581+ DeploymentTargetInfo.intersectWith (getCurrentTRC ()->getAvailabilityInfo ());
582+
583+ return TypeRefinementContext::createForResilienceBoundary (
584+ Context, D, getCurrentTRC (),
585+ DeploymentTargetInfo, range);
586+ }
587+
513588 std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
514589 if (auto *IS = dyn_cast<IfStmt>(S)) {
515590 buildIfStmtRefinementContext (IS);
@@ -927,8 +1002,8 @@ void TypeChecker::buildTypeRefinementContextHierarchy(SourceFile &SF) {
9271002 if (!RootTRC) {
9281003 // The root type refinement context reflects the fact that all parts of
9291004 // the source file are guaranteed to be executing on at least the minimum
930- // platform version.
931- auto MinPlatformReq = AvailabilityContext::forDeploymentTarget (Context);
1005+ // platform version for inlining .
1006+ auto MinPlatformReq = AvailabilityContext::forInliningTarget (Context);
9321007 RootTRC = TypeRefinementContext::createRoot (&SF, MinPlatformReq);
9331008 SF.setTypeRefinementContext (RootTRC);
9341009 }
@@ -993,9 +1068,8 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
9931068 // refined. For now, this is fine -- but if we ever synthesize #available(),
9941069 // this will be a real problem.
9951070
996- // We can assume we are running on at least the minimum deployment target.
997- auto OverApproximateContext =
998- AvailabilityContext::forDeploymentTarget (Context);
1071+ // We can assume we are running on at least the minimum inlining target.
1072+ auto OverApproximateContext = AvailabilityContext::forInliningTarget (Context);
9991073 auto isInvalidLoc = [SF](SourceLoc loc) {
10001074 return SF ? loc.isInvalid () : true ;
10011075 };
0 commit comments