Skip to content

Commit 02a1577

Browse files
authored
Merge pull request #63503 from artemcm/ConstExtractRuntimeMetadataAttr
[Compile Time Constant Extraction] Extract Runtime Metadata Attributes
2 parents 7c6bbff + d5f09b4 commit 02a1577

File tree

5 files changed

+143
-45
lines changed

5 files changed

+143
-45
lines changed

include/swift/AST/ConstTypeInfo.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class RuntimeValue : public CompileTimeValue {
195195
};
196196

197197
struct CustomAttrValue {
198-
swift::CustomAttr *Attr;
198+
const swift::CustomAttr *Attr;
199199
std::vector<FunctionParameter> Parameters;
200200
};
201201

@@ -212,20 +212,25 @@ struct EnumElementDeclValue {
212212
llvm::Optional<std::vector<EnumElementParameterValue>> Parameters;
213213
};
214214

215+
using AttrValueVector = llvm::SmallVector<CustomAttrValue, 2>;
215216
struct ConstValueTypePropertyInfo {
216217
swift::VarDecl *VarDecl;
217218
std::shared_ptr<CompileTimeValue> Value;
218-
llvm::Optional<std::vector<CustomAttrValue>> PropertyWrappers;
219+
llvm::Optional<AttrValueVector> PropertyWrappers;
220+
llvm::Optional<AttrValueVector> RuntimeMetadataAttributes;
219221

220222
ConstValueTypePropertyInfo(
221223
swift::VarDecl *VarDecl, std::shared_ptr<CompileTimeValue> Value,
222-
llvm::Optional<std::vector<CustomAttrValue>> PropertyWrappers)
223-
: VarDecl(VarDecl), Value(Value), PropertyWrappers(PropertyWrappers) {}
224+
llvm::Optional<AttrValueVector> PropertyWrappers,
225+
llvm::Optional<AttrValueVector> RuntimeMetadataAttributes)
226+
: VarDecl(VarDecl), Value(Value), PropertyWrappers(PropertyWrappers),
227+
RuntimeMetadataAttributes(RuntimeMetadataAttributes) {}
224228

225229
ConstValueTypePropertyInfo(swift::VarDecl *VarDecl,
226230
std::shared_ptr<CompileTimeValue> Value)
227231
: VarDecl(VarDecl), Value(Value),
228-
PropertyWrappers(llvm::Optional<std::vector<CustomAttrValue>>()) {}
232+
PropertyWrappers(llvm::Optional<AttrValueVector>()),
233+
RuntimeMetadataAttributes(llvm::Optional<AttrValueVector>()) {}
229234
};
230235

231236
struct ConstValueTypeInfo {

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5769,6 +5769,9 @@ class VarDecl : public AbstractStorageDecl {
57695769
/// that has an external effect on the function.
57705770
bool hasExternalPropertyWrapper() const;
57715771

5772+
/// Whether this property has any attached runtime metadata attributes.
5773+
bool hasRuntimeMetadataAttributes() const;
5774+
57725775
/// Whether all of the attached property wrappers have an init(wrappedValue:)
57735776
/// initializer.
57745777
bool allAttachedPropertyWrappersHaveWrappedValueInit() const;

lib/AST/Decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6814,6 +6814,11 @@ bool VarDecl::hasAttachedPropertyWrapper() const {
68146814
return false;
68156815
}
68166816

6817+
/// Whether this property has any attached runtime metadata attributes.
6818+
bool VarDecl::hasRuntimeMetadataAttributes() const {
6819+
return !getRuntimeDiscoverableAttrs().empty();
6820+
}
6821+
68176822
bool VarDecl::hasImplicitPropertyWrapper() const {
68186823
if (getAttrs().hasAttribute<CustomAttr>()) {
68196824
if (!getAttachedPropertyWrappers().empty())

lib/ConstExtract/ConstExtract.cpp

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -303,42 +303,52 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
303303
return std::make_shared<RuntimeValue>();
304304
}
305305

306-
static std::vector<CustomAttrValue>
307-
extractCustomAttrValues(VarDecl *propertyDecl) {
308-
std::vector<CustomAttrValue> customAttrValues;
309-
310-
for (auto *propertyWrapper : propertyDecl->getAttachedPropertyWrappers()) {
311-
std::vector<FunctionParameter> parameters;
312-
313-
if (const auto *args = propertyWrapper->getArgs()) {
314-
for (auto arg : *args) {
315-
const auto label = arg.getLabel().str().str();
316-
auto argExpr = arg.getExpr();
317-
318-
if (auto defaultArgument = dyn_cast<DefaultArgumentExpr>(argExpr)) {
319-
auto *decl = defaultArgument->getParamDecl();
320-
if (decl->hasDefaultExpr()) {
321-
argExpr = decl->getTypeCheckedDefaultExpr();
322-
}
306+
static CustomAttrValue
307+
extractAttributeValue(const CustomAttr *attr) {
308+
std::vector<FunctionParameter> parameters;
309+
if (const auto *args = attr->getArgs()) {
310+
for (auto arg : *args) {
311+
const auto label = arg.getLabel().str().str();
312+
auto argExpr = arg.getExpr();
313+
314+
if (auto defaultArgument = dyn_cast<DefaultArgumentExpr>(argExpr)) {
315+
auto *decl = defaultArgument->getParamDecl();
316+
if (decl->hasDefaultExpr()) {
317+
argExpr = decl->getTypeCheckedDefaultExpr();
323318
}
324-
parameters.push_back(
325-
{label, argExpr->getType(), extractCompileTimeValue(argExpr)});
326319
}
320+
parameters.push_back(
321+
{label, argExpr->getType(), extractCompileTimeValue(argExpr)});
327322
}
328-
329-
customAttrValues.push_back({propertyWrapper, parameters});
330323
}
324+
return {attr, parameters};
325+
}
331326

327+
static AttrValueVector
328+
extractPropertyWrapperAttrValues(VarDecl *propertyDecl) {
329+
AttrValueVector customAttrValues;
330+
for (auto *propertyWrapper : propertyDecl->getAttachedPropertyWrappers())
331+
customAttrValues.push_back(extractAttributeValue(propertyWrapper));
332+
return customAttrValues;
333+
}
334+
335+
static AttrValueVector
336+
extractRuntimeMetadataAttrValues(VarDecl *propertyDecl) {
337+
AttrValueVector customAttrValues;
338+
for (auto *runtimeMetadataAttribute : propertyDecl->getRuntimeDiscoverableAttrs())
339+
customAttrValues.push_back(extractAttributeValue(runtimeMetadataAttribute));
332340
return customAttrValues;
333341
}
334342

335343
static ConstValueTypePropertyInfo
336344
extractTypePropertyInfo(VarDecl *propertyDecl) {
337345
if (const auto binding = propertyDecl->getParentPatternBinding()) {
338346
if (const auto originalInit = binding->getInit(0)) {
339-
if (propertyDecl->hasAttachedPropertyWrapper()) {
347+
if (propertyDecl->hasAttachedPropertyWrapper() ||
348+
propertyDecl->hasRuntimeMetadataAttributes()) {
340349
return {propertyDecl, extractCompileTimeValue(originalInit),
341-
extractCustomAttrValues(propertyDecl)};
350+
extractPropertyWrapperAttrValues(propertyDecl),
351+
extractRuntimeMetadataAttrValues(propertyDecl)};
342352
}
343353

344354
return {propertyDecl, extractCompileTimeValue(originalInit)};
@@ -578,31 +588,51 @@ void writeValue(llvm::json::OStream &JSON,
578588
}
579589
}
580590

591+
void writeAttributeInfo(llvm::json::OStream &JSON,
592+
const CustomAttrValue &AttrVal,
593+
const ASTContext &ctx) {
594+
JSON.object([&] {
595+
JSON.attribute("type",
596+
toFullyQualifiedTypeNameString(AttrVal.Attr->getType()));
597+
writeLocationInformation(JSON, AttrVal.Attr->getLocation(), ctx);
598+
JSON.attributeArray("arguments", [&] {
599+
for (auto FP : AttrVal.Parameters) {
600+
JSON.object([&] {
601+
JSON.attribute("label", FP.Label);
602+
JSON.attribute("type", toFullyQualifiedTypeNameString(FP.Type));
603+
writeValue(JSON, FP.Value);
604+
});
605+
}
606+
});
607+
});
608+
}
609+
581610
void writePropertyWrapperAttributes(
582611
llvm::json::OStream &JSON,
583-
llvm::Optional<std::vector<CustomAttrValue>> PropertyWrappers,
612+
llvm::Optional<AttrValueVector> PropertyWrappers,
584613
const ASTContext &ctx) {
585614
if (!PropertyWrappers.has_value()) {
586615
return;
587616
}
588617

589618
JSON.attributeArray("propertyWrappers", [&] {
590-
for (auto PW : PropertyWrappers.value()) {
591-
JSON.object([&] {
592-
JSON.attribute("type",
593-
toFullyQualifiedTypeNameString(PW.Attr->getType()));
594-
writeLocationInformation(JSON, PW.Attr->getLocation(), ctx);
595-
JSON.attributeArray("arguments", [&] {
596-
for (auto FP : PW.Parameters) {
597-
JSON.object([&] {
598-
JSON.attribute("label", FP.Label);
599-
JSON.attribute("type", toFullyQualifiedTypeNameString(FP.Type));
600-
writeValue(JSON, FP.Value);
601-
});
602-
}
603-
});
604-
});
605-
}
619+
for (auto PW : PropertyWrappers.value())
620+
writeAttributeInfo(JSON, PW, ctx);
621+
});
622+
}
623+
624+
void writeRuntimeMetadataAttributes(
625+
llvm::json::OStream &JSON,
626+
llvm::Optional<AttrValueVector> RuntimeMetadataAttributes,
627+
const ASTContext &ctx) {
628+
if (!RuntimeMetadataAttributes.has_value() ||
629+
RuntimeMetadataAttributes.value().empty()) {
630+
return;
631+
}
632+
633+
JSON.attributeArray("runtimeMetadataAttributes", [&] {
634+
for (auto RMA : RuntimeMetadataAttributes.value())
635+
writeAttributeInfo(JSON, RMA, ctx);;
606636
});
607637
}
608638

@@ -737,6 +767,8 @@ bool writeAsJSONToFile(const std::vector<ConstValueTypeInfo> &ConstValueInfos,
737767
writeValue(JSON, PropertyInfo.Value);
738768
writePropertyWrapperAttributes(
739769
JSON, PropertyInfo.PropertyWrappers, decl->getASTContext());
770+
writeRuntimeMetadataAttributes(
771+
JSON, PropertyInfo.RuntimeMetadataAttributes, decl->getASTContext());
740772
writeResultBuilderInformation(JSON, TypeDecl, decl);
741773
writeAttrInformation(JSON, decl->getAttrs());
742774
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: echo "[MyProto]" > %t/protocols.json
3+
4+
// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractRuntimeMetadataAttr.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s -enable-experimental-feature RuntimeDiscoverableAttrs
5+
// RUN: cat %t/ExtractRuntimeMetadataAttr.swiftconstvalues 2>&1 | %FileCheck %s
6+
7+
@runtimeMetadata
8+
struct Flag<T> {
9+
init(attachedTo: T.Type, _ description: String = "") {}
10+
init<Args>(attachedTo: (Args) -> T, _ description: String = "") {}
11+
init<Base>(attachedTo: KeyPath<Base, T>, _ description: String = "") {}
12+
}
13+
14+
protocol MyProto {}
15+
16+
struct A : MyProto {
17+
@Flag("v1") var v1: String = "foo"
18+
}
19+
20+
// CHECK: "typeName": "ExtractRuntimeMetadataAttr.A",
21+
// CHECK-NEXT: "kind": "struct",
22+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractRuntimeMetadataAttr.swift",
23+
// CHECK-NEXT: "line": 16,
24+
// CHECK-NEXT: "properties": [
25+
// CHECK-NEXT: {
26+
// CHECK-NEXT: "label": "v1",
27+
// CHECK-NEXT: "type": "Swift.String",
28+
// CHECK-NEXT: "isStatic": "false",
29+
// CHECK-NEXT: "isComputed": "false",
30+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractRuntimeMetadataAttr.swift",
31+
// CHECK-NEXT: "line": 17,
32+
// CHECK-NEXT: "valueKind": "RawLiteral",
33+
// CHECK-NEXT: "value": "foo",
34+
// CHECK-NEXT: "propertyWrappers": [],
35+
// CHECK-NEXT: "runtimeMetadataAttributes": [
36+
// CHECK-NEXT: {
37+
// CHECK-NEXT: "type": "ExtractRuntimeMetadataAttr.Flag",
38+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractRuntimeMetadataAttr.swift",
39+
// CHECK-NEXT: "line": 17,
40+
// CHECK-NEXT: "arguments": [
41+
// CHECK-NEXT: {
42+
// CHECK-NEXT: "label": "",
43+
// CHECK-NEXT: "type": "Swift.String",
44+
// CHECK-NEXT: "valueKind": "RawLiteral",
45+
// CHECK-NEXT: "value": "v1"
46+
// CHECK-NEXT: }
47+
// CHECK-NEXT: ]
48+
// CHECK-NEXT: }
49+
// CHECK-NEXT: ]
50+
// CHECK-NEXT: }
51+
// CHECK-NEXT: ]
52+
// CHECK-NEXT: }
53+
// CHECK-NEXT:]

0 commit comments

Comments
 (0)