[Compile Time Constant Extraction] Extract from extensions of types not declared in the same file/module (#70081)

Resolves rdar://118904022
This commit is contained in:
Zhiyu Zhu/朱智语
2023-11-29 09:07:52 -08:00
committed by GitHub
parent 9d1a92eb72
commit 6d3017cde3
5 changed files with 112 additions and 33 deletions

View File

@@ -53,14 +53,21 @@ public:
}
PreWalkAction walkToDeclPre(Decl *D) override {
if (auto *NTD = llvm::dyn_cast<NominalTypeDecl>(D))
if (!isa<ProtocolDecl>(NTD))
auto *NTD = llvm::dyn_cast<NominalTypeDecl>(D);
if (!NTD)
if (auto *ETD = dyn_cast<ExtensionDecl>(D))
NTD = ETD->getExtendedNominal();
if (NTD)
if (!isa<ProtocolDecl>(NTD) && CheckedDecls.insert(NTD).second)
for (auto &Protocol : NTD->getAllProtocols())
if (Protocol->getAttrs().hasAttribute<ExtractConstantsFromMembersAttr>() ||
Protocols.count(Protocol->getName().str().str()) != 0)
ConformanceTypeDecls.push_back(NTD);
return Action::Continue();
}
private:
std::unordered_set<NominalTypeDecl *> CheckedDecls;
};
std::string toFullyQualifiedTypeNameString(const swift::Type &Type) {
@@ -463,37 +470,52 @@ extractEnumCases(NominalTypeDecl *Decl) {
return llvm::None;
}
ConstValueTypeInfo
ConstantValueInfoRequest::evaluate(Evaluator &Evaluator,
NominalTypeDecl *Decl) const {
// Use 'getStoredProperties' to get lowered lazy and wrapped properties
auto StoredProperties = Decl->getStoredProperties();
std::unordered_set<VarDecl *> StoredPropertiesSet(StoredProperties.begin(),
StoredProperties.end());
ConstValueTypeInfo ConstantValueInfoRequest::evaluate(
Evaluator &Evaluator, NominalTypeDecl *Decl,
llvm::PointerUnion<const SourceFile *, ModuleDecl *> extractionScope)
const {
auto shouldExtract = [&](DeclContext *decl) {
if (auto SF = extractionScope.dyn_cast<const SourceFile *>())
return decl->getOutermostParentSourceFile() == SF;
return decl->getParentModule() == extractionScope.get<ModuleDecl *>();
};
std::vector<ConstValueTypePropertyInfo> Properties;
for (auto Property : StoredProperties) {
Properties.push_back(extractTypePropertyInfo(Property));
}
llvm::Optional<std::vector<EnumElementDeclValue>> EnumCases;
for (auto Member : Decl->getMembers()) {
auto *VD = dyn_cast<VarDecl>(Member);
// Ignore plain stored properties collected above,
// instead gather up remaining static and computed properties.
if (!VD || StoredPropertiesSet.count(VD))
continue;
Properties.push_back(extractTypePropertyInfo(VD));
if (shouldExtract(Decl)) {
// Use 'getStoredProperties' to get lowered lazy and wrapped properties
auto StoredProperties = Decl->getStoredProperties();
std::unordered_set<VarDecl *> StoredPropertiesSet(StoredProperties.begin(),
StoredProperties.end());
for (auto Property : StoredProperties) {
Properties.push_back(extractTypePropertyInfo(Property));
}
for (auto Member : Decl->getMembers()) {
auto *VD = dyn_cast<VarDecl>(Member);
// Ignore plain stored properties collected above,
// instead gather up remaining static and computed properties.
if (!VD || StoredPropertiesSet.count(VD))
continue;
Properties.push_back(extractTypePropertyInfo(VD));
}
EnumCases = extractEnumCases(Decl);
}
for (auto Extension: Decl->getExtensions()) {
for (auto Member : Extension->getMembers()) {
if (auto *VD = dyn_cast<VarDecl>(Member)) {
Properties.push_back(extractTypePropertyInfo(VD));
if (shouldExtract(Extension)) {
for (auto Member : Extension->getMembers()) {
if (auto *VD = dyn_cast<VarDecl>(Member)) {
Properties.push_back(extractTypePropertyInfo(VD));
}
}
}
}
return ConstValueTypeInfo{Decl, Properties, extractEnumCases(Decl)};
return ConstValueTypeInfo{Decl, Properties, EnumCases};
}
std::vector<ConstValueTypeInfo>
@@ -507,7 +529,8 @@ gatherConstValuesForModule(const std::unordered_set<std::string> &Protocols,
Module->walk(ConformanceCollector);
for (auto *CD : ConformanceDecls)
Result.emplace_back(evaluateOrDefault(CD->getASTContext().evaluator,
ConstantValueInfoRequest{CD}, {}));
ConstantValueInfoRequest{CD, Module},
{}));
return Result;
}
@@ -523,8 +546,8 @@ gatherConstValuesForPrimary(const std::unordered_set<std::string> &Protocols,
D->walk(ConformanceCollector);
for (auto *CD : ConformanceDecls)
Result.emplace_back(evaluateOrDefault(CD->getASTContext().evaluator,
ConstantValueInfoRequest{CD}, {}));
Result.emplace_back(evaluateOrDefault(
CD->getASTContext().evaluator, ConstantValueInfoRequest{CD, SF}, {}));
return Result;
}