Skip to content

Commit fd4feac

Browse files
committed
[AST] Intro request to list declared and inherited SPI groups
1 parent b8a87f6 commit fd4feac

File tree

5 files changed

+81
-11
lines changed

5 files changed

+81
-11
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)
5454
SWIFT_TYPEID_NAMED(ValueDecl *, ValueDecl)
5555
SWIFT_TYPEID_NAMED(VarDecl *, VarDecl)
5656
SWIFT_TYPEID(FingerprintAndMembers)
57+
SWIFT_TYPEID(Identifier)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct TypeWitnessAndDecl;
6262
enum class AncestryFlags : uint8_t;
6363
enum class ImplicitMemberAction : uint8_t;
6464
struct FingerprintAndMembers;
65+
class Identifier;
6566

6667
// Define the AST type zone (zone 1)
6768
#define SWIFT_TYPEID_ZONE AST

include/swift/AST/TypeCheckRequests.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,26 @@ class PatternTypeRequest
20252025
}
20262026
};
20272027

2028+
/// List SPI group ids declared on a decl.
2029+
class SPIGroupsRequest :
2030+
public SimpleRequest<SPIGroupsRequest,
2031+
llvm::ArrayRef<Identifier>(const Decl *),
2032+
CacheKind::Cached> {
2033+
public:
2034+
using SimpleRequest::SimpleRequest;
2035+
2036+
private:
2037+
friend SimpleRequest;
2038+
2039+
// Evaluation.
2040+
llvm::Expected<llvm::ArrayRef<Identifier>>
2041+
evaluate(Evaluator &evaluator, const Decl *decl) const;
2042+
2043+
public:
2044+
bool isCached() const { return true; }
2045+
};
2046+
2047+
20282048
/// Type-checks a `@differentiable` attribute and returns the resolved parameter
20292049
/// indices on success. On failure, emits diagnostics and returns `nullptr`.
20302050
///

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ SWIFT_REQUEST(TypeChecker, IsDynamicRequest, bool(ValueDecl *),
105105
SeparatelyCached, NoLocationInfo)
106106
SWIFT_REQUEST(TypeChecker, IsFinalRequest, bool(ValueDecl *), SeparatelyCached,
107107
NoLocationInfo)
108+
SWIFT_REQUEST(TypeChecker, SPIGroupsRequest,
109+
llvm::ArrayRef<Identifier>(Decl *),
110+
Cached, NoLocationInfo)
108111
SWIFT_REQUEST(TypeChecker, IsGetterMutatingRequest, bool(AbstractStorageDecl *),
109112
SeparatelyCached, NoLocationInfo)
110113
SWIFT_REQUEST(TypeChecker, IsImplicitlyUnwrappedOptionalRequest,

lib/AST/Module.cpp

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,22 +1820,67 @@ void SourceFile::lookupImportedSPIGroups(const ModuleDecl *importedModule,
18201820
}
18211821

18221822
bool SourceFile::isImportedAsSPI(const ValueDecl *targetDecl) const {
1823-
if (!targetDecl->getAttrs().hasAttribute<SPIAccessControlAttr>())
1824-
return false;
1825-
18261823
auto targetModule = targetDecl->getModuleContext();
1827-
SmallVector<Identifier, 4> importedSpis;
1828-
lookupImportedSPIGroups(targetModule, importedSpis);
1829-
1830-
for (auto attr : targetDecl->getAttrs().getAttributes<SPIAccessControlAttr>())
1831-
for (auto declSPI : attr->getSPIGroups())
1832-
for (auto importedSPI : importedSpis)
1833-
if (importedSPI == declSPI)
1834-
return true;
1824+
SmallVector<Identifier, 4> importedSPIGroups;
1825+
lookupImportedSPIGroups(targetModule, importedSPIGroups);
1826+
if (importedSPIGroups.empty()) return false;
1827+
1828+
auto declSPIGroups = evaluateOrDefault(
1829+
targetDecl->getASTContext().evaluator,
1830+
SPIGroupsRequest{ targetDecl },
1831+
ArrayRef<Identifier>());
1832+
1833+
// Note: If we reach a point where there are many SPI imports or SPI groups
1834+
// on decls we could optimize this further by using a set.
1835+
for (auto importedSPI : importedSPIGroups)
1836+
for (auto declSPI : declSPIGroups)
1837+
if (importedSPI == declSPI)
1838+
return true;
18351839

18361840
return false;
18371841
}
18381842

1843+
llvm::Expected<llvm::ArrayRef<Identifier>>
1844+
SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
1845+
// Applies only to public ValueDecls and ExtensionDecls.
1846+
if (auto vd = dyn_cast<ValueDecl>(decl)) {
1847+
if (vd->getFormalAccess() < AccessLevel::Public)
1848+
return ArrayRef<Identifier>();
1849+
} else if (!isa<ExtensionDecl>(decl))
1850+
return ArrayRef<Identifier>();
1851+
1852+
// First, look for local attributes.
1853+
llvm::SetVector<Identifier> spiGroups;
1854+
for (auto attr : decl->getAttrs().getAttributes<SPIAccessControlAttr>())
1855+
for (auto spi : attr->getSPIGroups())
1856+
spiGroups.insert(spi);
1857+
1858+
auto &ctx = decl->getASTContext();
1859+
if (spiGroups.empty()) {
1860+
1861+
// Then in the extended nominal type.
1862+
if (auto extension = dyn_cast<ExtensionDecl>(decl)) {
1863+
auto extended = extension->getExtendedNominal();
1864+
auto extSPIs = evaluateOrDefault(ctx.evaluator,
1865+
SPIGroupsRequest{ extended },
1866+
ArrayRef<Identifier>());
1867+
if (!extSPIs.empty()) return extSPIs;
1868+
}
1869+
1870+
// And finally in the parent context.
1871+
auto parent = decl->getDeclContext();
1872+
if (auto parentD = parent->getAsDecl()) {
1873+
if (!isa<ModuleDecl>(parentD)) {
1874+
return evaluateOrDefault(ctx.evaluator,
1875+
SPIGroupsRequest{ parentD },
1876+
ArrayRef<Identifier>());
1877+
}
1878+
}
1879+
}
1880+
1881+
return ctx.AllocateCopy(spiGroups.getArrayRef());
1882+
}
1883+
18391884
bool SourceFile::shouldCrossImport() const {
18401885
return Kind != SourceFileKind::SIL && Kind != SourceFileKind::Interface &&
18411886
getASTContext().LangOpts.EnableCrossImportOverlays;

0 commit comments

Comments
 (0)