Skip to content

Commit f62620f

Browse files
authored
Merge pull request #31060 from slavapestov/fix-fragile-function-kind-crash
Fix crash with invalid private @inlinable function
2 parents f5fa89b + e2349bd commit f62620f

14 files changed

+173
-159
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ SWIFT_TYPEID(PropertyWrapperBackingPropertyInfo)
2525
SWIFT_TYPEID(PropertyWrapperTypeInfo)
2626
SWIFT_TYPEID(Requirement)
2727
SWIFT_TYPEID(ResilienceExpansion)
28+
SWIFT_TYPEID(FragileFunctionKind)
2829
SWIFT_TYPEID(Type)
2930
SWIFT_TYPEID(TypePair)
3031
SWIFT_TYPEID(TypeWitnessAndDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct PropertyWrapperMutability;
5353
class ProtocolDecl;
5454
class Requirement;
5555
enum class ResilienceExpansion : unsigned;
56+
struct FragileFunctionKind;
5657
class SourceFile;
5758
class Type;
5859
class ValueDecl;

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4930,7 +4930,7 @@ class VarDecl : public AbstractStorageDecl {
49304930
PointerUnion<PatternBindingDecl *, Stmt *, VarDecl *> Parent;
49314931

49324932
VarDecl(DeclKind kind, bool isStatic, Introducer introducer,
4933-
bool issCaptureList, SourceLoc nameLoc, Identifier name,
4933+
bool isCaptureList, SourceLoc nameLoc, Identifier name,
49344934
DeclContext *dc, StorageIsMutable_t supportsMutation);
49354935

49364936
public:

include/swift/AST/DeclContext.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,26 @@ struct ConformanceDiagnostic {
179179
ProtocolDecl *ExistingExplicitProtocol;
180180
};
181181

182+
/// Used in diagnostic %selects.
183+
struct FragileFunctionKind {
184+
enum Kind : unsigned {
185+
Transparent,
186+
Inlinable,
187+
AlwaysEmitIntoClient,
188+
DefaultArgument,
189+
PropertyInitializer,
190+
None
191+
};
192+
193+
Kind kind = None;
194+
bool allowUsableFromInline = false;
195+
196+
friend bool operator==(FragileFunctionKind lhs, FragileFunctionKind rhs) {
197+
return (lhs.kind == rhs.kind &&
198+
lhs.allowUsableFromInline == rhs.allowUsableFromInline);
199+
}
200+
};
201+
182202
/// A DeclContext is an AST object which acts as a semantic container
183203
/// for declarations. As a policy matter, we currently define
184204
/// contexts broadly: a lambda expression in a function is a new
@@ -469,6 +489,10 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
469489
/// are used.
470490
ResilienceExpansion getResilienceExpansion() const;
471491

492+
/// Get the fragile function kind for the code in this context, which
493+
/// is used for diagnostics.
494+
FragileFunctionKind getFragileFunctionKind() const;
495+
472496
/// Returns true if this context may possibly contain members visible to
473497
/// AnyObject dynamic lookup.
474498
bool mayContainMembersAccessedByDynamicLookup() const;

include/swift/AST/TypeCheckRequests.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -672,10 +672,10 @@ class StructuralTypeRequest :
672672
bool isCached() const { return true; }
673673
};
674674

675-
/// Request the most optimal resilience expansion for the code in the context.
676-
class ResilienceExpansionRequest :
677-
public SimpleRequest<ResilienceExpansionRequest,
678-
ResilienceExpansion(DeclContext*),
675+
/// Request the fragile function kind for the context.
676+
class FragileFunctionKindRequest :
677+
public SimpleRequest<FragileFunctionKindRequest,
678+
FragileFunctionKind(DeclContext*),
679679
RequestFlags::Cached> {
680680
public:
681681
using SimpleRequest::SimpleRequest;
@@ -684,15 +684,16 @@ class ResilienceExpansionRequest :
684684
friend SimpleRequest;
685685

686686
// Evaluation.
687-
ResilienceExpansion evaluate(Evaluator &eval, DeclContext *context) const;
687+
FragileFunctionKind evaluate(Evaluator &eval, DeclContext *context) const;
688688

689689
public:
690690
// Caching.
691691
bool isCached() const { return true; }
692692
};
693693

694-
void simple_display(llvm::raw_ostream &out,
695-
const ResilienceExpansion &value);
694+
void simple_display(llvm::raw_ostream &out, FragileFunctionKind value);
695+
696+
void simple_display(llvm::raw_ostream &out, ResilienceExpansion value);
696697

697698
/// Request the custom attribute which attaches a function builder to the
698699
/// given declaration.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ SWIFT_REQUEST(TypeChecker, RequiresOpaqueAccessorsRequest, bool(VarDecl *),
168168
SeparatelyCached, NoLocationInfo)
169169
SWIFT_REQUEST(TypeChecker, RequiresOpaqueModifyCoroutineRequest,
170170
bool(AbstractStorageDecl *), SeparatelyCached, NoLocationInfo)
171-
SWIFT_REQUEST(TypeChecker, ResilienceExpansionRequest,
172-
ResilienceExpansion(DeclContext *), Cached, NoLocationInfo)
171+
SWIFT_REQUEST(TypeChecker, FragileFunctionKindRequest,
172+
FragileFunctionKind(DeclContext *), Cached, NoLocationInfo)
173173
SWIFT_REQUEST(TypeChecker, SelfAccessKindRequest, SelfAccessKind(FuncDecl *),
174174
SeparatelyCached, NoLocationInfo)
175175
SWIFT_REQUEST(TypeChecker, StorageImplInfoRequest,

lib/AST/DeclContext.cpp

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
319315
ResilienceExpansion 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.

lib/AST/TypeCheckRequests.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,8 +616,42 @@ void swift::simple_display(llvm::raw_ostream &os, PropertyWrapperMutability m) {
616616
}
617617

618618
void swift::simple_display(llvm::raw_ostream &out,
619-
const ResilienceExpansion &value) {
620-
out << value;
619+
ResilienceExpansion value) {
620+
switch (value) {
621+
case ResilienceExpansion::Minimal:
622+
out << "minimal";
623+
break;
624+
case ResilienceExpansion::Maximal:
625+
out << "maximal";
626+
break;
627+
}
628+
}
629+
630+
void swift::simple_display(llvm::raw_ostream &out,
631+
FragileFunctionKind value) {
632+
switch (value.kind) {
633+
case FragileFunctionKind::Transparent:
634+
out << "transparent";
635+
break;
636+
case FragileFunctionKind::Inlinable:
637+
out << "inlinable";
638+
break;
639+
case FragileFunctionKind::AlwaysEmitIntoClient:
640+
out << "alwaysEmitIntoClient";
641+
break;
642+
case FragileFunctionKind::DefaultArgument:
643+
out << "defaultArgument";
644+
break;
645+
case FragileFunctionKind::PropertyInitializer:
646+
out << "propertyInitializer";
647+
break;
648+
case FragileFunctionKind::None:
649+
out << "none";
650+
break;
651+
}
652+
653+
out << ", allowUsableFromInline: "
654+
<< (value.allowUsableFromInline ? "true" : "false");
621655
}
622656

623657
//----------------------------------------------------------------------------//

0 commit comments

Comments
 (0)