@@ -312,19 +312,31 @@ bool DeclContext::isGenericContext() const {
312312 return false ;
313313}
314314
315- // / Get the most optimal resilience expansion for the body of this function.
316- // / If the body is able to be inlined into functions in other resilience
317- // / domains, this ensures that only sufficiently-conservative access patterns
318- // / are used.
319315ResilienceExpansion DeclContext::getResilienceExpansion () const {
316+ auto fragileKind = getFragileFunctionKind ();
317+ switch (fragileKind.kind ) {
318+ case FragileFunctionKind::Transparent:
319+ case FragileFunctionKind::Inlinable:
320+ case FragileFunctionKind::AlwaysEmitIntoClient:
321+ case FragileFunctionKind::DefaultArgument:
322+ case FragileFunctionKind::PropertyInitializer:
323+ return ResilienceExpansion::Minimal;
324+ case FragileFunctionKind::None:
325+ return ResilienceExpansion::Maximal;
326+ }
327+
328+ llvm_unreachable (" Bad fragile function kind" );
329+ }
330+
331+ FragileFunctionKind DeclContext::getFragileFunctionKind () const {
320332 auto &context = getASTContext ();
321333 return evaluateOrDefault (context.evaluator ,
322- ResilienceExpansionRequest { const_cast <DeclContext *>(this ) },
323- ResilienceExpansion::Minimal );
334+ FragileFunctionKindRequest { const_cast <DeclContext *>(this ) },
335+ {FragileFunctionKind::None, false } );
324336}
325337
326- ResilienceExpansion
327- swift::ResilienceExpansionRequest ::evaluate (Evaluator &evaluator,
338+ FragileFunctionKind
339+ swift::FragileFunctionKindRequest ::evaluate (Evaluator &evaluator,
328340 DeclContext *context) const {
329341 for (const auto *dc = context->getLocalContext (); dc && dc->isLocalContext ();
330342 dc = dc->getParent ()) {
@@ -336,14 +348,19 @@ swift::ResilienceExpansionRequest::evaluate(Evaluator &evaluator,
336348 auto *VD = cast<ValueDecl>(dc->getAsDecl ());
337349 assert (VD->hasParameterList ());
338350
339- auto access =
351+ auto effectiveAccess =
340352 VD->getFormalAccessScope (/* useDC=*/ nullptr ,
341353 /* treatUsableFromInlineAsPublic=*/ true );
354+ auto formalAccess =
355+ VD->getFormalAccessScope (/* useDC=*/ nullptr ,
356+ /* treatUsableFromInlineAsPublic=*/ false );
357+ if (effectiveAccess.isPublic ()) {
358+ return {FragileFunctionKind::DefaultArgument,
359+ !formalAccess.isPublic ()};
360+ }
342361
343- if (access.isPublic ())
344- return ResilienceExpansion::Minimal;
345-
346- return ResilienceExpansion::Maximal;
362+ return {FragileFunctionKind::None,
363+ /* allowUsableFromInline=*/ false };
347364 }
348365
349366 // Stored property initializer contexts use minimal resilience expansion
@@ -354,12 +371,14 @@ swift::ResilienceExpansionRequest::evaluate(Evaluator &evaluator,
354371 NTD->getFormalAccessScope (/* useDC=*/ nullptr ,
355372 /* treatUsableFromInlineAsPublic=*/ true );
356373 if (!nominalAccess.isPublic ())
357- return ResilienceExpansion::Maximal;
374+ return {FragileFunctionKind::None,
375+ /* allowUsableFromInline=*/ false };
358376
359377 if (NTD->isFormallyResilient ())
360- return ResilienceExpansion::Maximal;
378+ return {FragileFunctionKind::None,
379+ /* allowUsableFromInline=*/ false };
361380
362- return ResilienceExpansion::Minimal ;
381+ return {FragileFunctionKind::PropertyInitializer, true } ;
363382 }
364383 }
365384
@@ -375,32 +394,44 @@ swift::ResilienceExpansionRequest::evaluate(Evaluator &evaluator,
375394
376395 // If the function is not externally visible, we will not be serializing
377396 // its body.
378- if (!funcAccess.isPublic ())
379- break ;
397+ if (!funcAccess.isPublic ()) {
398+ return {FragileFunctionKind::None,
399+ /* allowUsableFromInline=*/ false };
400+ }
380401
381402 // If the function is public, @_transparent implies @inlinable.
382- if (AFD->isTransparent ())
383- return ResilienceExpansion::Minimal;
403+ if (AFD->isTransparent ()) {
404+ return {FragileFunctionKind::Transparent,
405+ /* allowUsableFromInline=*/ true };
406+ }
384407
385- if (AFD->getAttrs ().hasAttribute <InlinableAttr>())
386- return ResilienceExpansion::Minimal;
408+ if (AFD->getAttrs ().hasAttribute <InlinableAttr>()) {
409+ return {FragileFunctionKind::Inlinable,
410+ /* allowUsableFromInline=*/ true };
411+ }
387412
388- if (AFD->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
389- return ResilienceExpansion::Minimal;
413+ if (AFD->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>()) {
414+ return {FragileFunctionKind::AlwaysEmitIntoClient,
415+ /* allowUsableFromInline=*/ true };
416+ }
390417
391418 // If a property or subscript is @inlinable or @_alwaysEmitIntoClient,
392419 // the accessors are @inlinable or @_alwaysEmitIntoClient also.
393420 if (auto accessor = dyn_cast<AccessorDecl>(AFD)) {
394421 auto *storage = accessor->getStorage ();
395- if (storage->getAttrs ().getAttribute <InlinableAttr>())
396- return ResilienceExpansion::Minimal;
397- if (storage->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
398- return ResilienceExpansion::Minimal;
422+ if (storage->getAttrs ().getAttribute <InlinableAttr>()) {
423+ return {FragileFunctionKind::Inlinable,
424+ /* allowUsableFromInline=*/ true };
425+ }
426+ if (storage->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>()) {
427+ return {FragileFunctionKind::AlwaysEmitIntoClient,
428+ /* allowUsableFromInline=*/ true };
429+ }
399430 }
400431 }
401432 }
402433
403- return ResilienceExpansion::Maximal ;
434+ return {FragileFunctionKind::None, false } ;
404435}
405436
406437// / Determine whether the innermost context is generic.
0 commit comments