Skip to content

Commit 9d1a92e

Browse files
authored
[Compile Time Constant Extraction] Add @extractConstantsFromMembers (#69944)
Add @extractConstantsFromMembers attribute under ExtractConstantsFromMembers experimental feature flag
1 parent d5ef460 commit 9d1a92e

11 files changed

+53
-2
lines changed

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,9 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(_resultDependsOnSelf, ResultDependsOnSelf,
533533
SIMPLE_DECL_ATTR(_staticExclusiveOnly, StaticExclusiveOnly,
534534
OnStruct | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
535535
151)
536+
SIMPLE_DECL_ATTR(extractConstantsFromMembers, ExtractConstantsFromMembers,
537+
OnProtocol | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
538+
152)
536539

537540
#undef TYPE_ATTR
538541
#undef DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,10 @@ ERROR(attr_static_exclusive_only_let_only_param,none,
19351935
ERROR(attr_static_exclusive_only_mutating,none,
19361936
"type %0 cannot have mutating function %1", (Type, ValueDecl *))
19371937

1938+
// @extractConstantsFromMembers
1939+
ERROR(attr_extractConstantsFromMembers_experimental,none,
1940+
"@extractConstantsFromMembers requires '-enable-experimental-feature ExtractConstantsFromMembers'", ())
1941+
19381942
ERROR(c_func_variadic, none,
19391943
"cannot declare variadic argument %0 in %kind1",
19401944
(DeclName, const ValueDecl *))

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ EXPERIMENTAL_FEATURE(InferSendableFromCaptures, false)
263263
/// Enable the `@_staticExclusiveOnly` attribute.
264264
EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)
265265

266+
/// Enable the @extractConstantsFromMembers attribute.
267+
EXPERIMENTAL_FEATURE(ExtractConstantsFromMembers, false)
268+
266269
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
267270
#undef EXPERIMENTAL_FEATURE
268271
#undef UPCOMING_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,6 +3648,10 @@ static bool usesFeatureStaticExclusiveOnly(Decl *decl) {
36483648
return decl->getAttrs().hasAttribute<StaticExclusiveOnlyAttr>();
36493649
}
36503650

3651+
static bool usesFeatureExtractConstantsFromMembers(Decl *decl) {
3652+
return decl->getAttrs().hasAttribute<ExtractConstantsFromMembersAttr>();
3653+
}
3654+
36513655
/// Suppress the printing of a particular feature.
36523656
static void suppressingFeature(PrintOptions &options, Feature feature,
36533657
llvm::function_ref<void()> action) {

lib/ConstExtract/ConstExtract.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class NominalTypeConformanceCollector : public ASTWalker {
5656
if (auto *NTD = llvm::dyn_cast<NominalTypeDecl>(D))
5757
if (!isa<ProtocolDecl>(NTD))
5858
for (auto &Protocol : NTD->getAllProtocols())
59-
if (Protocols.count(Protocol->getName().str().str()) != 0)
59+
if (Protocol->getAttrs().hasAttribute<ExtractConstantsFromMembersAttr>() ||
60+
Protocols.count(Protocol->getName().str().str()) != 0)
6061
ConformanceTypeDecls.push_back(NTD);
6162
return Action::Continue();
6263
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
330330

331331
void visitAlwaysEmitConformanceMetadataAttr(AlwaysEmitConformanceMetadataAttr *attr);
332332

333+
void visitExtractConstantsFromMembersAttr(ExtractConstantsFromMembersAttr *attr);
334+
333335
void visitUnavailableFromAsyncAttr(UnavailableFromAsyncAttr *attr);
334336

335337
void visitUnsafeInheritExecutorAttr(UnsafeInheritExecutorAttr *attr);
@@ -430,6 +432,13 @@ void AttributeChecker::visitAlwaysEmitConformanceMetadataAttr(AlwaysEmitConforma
430432
return;
431433
}
432434

435+
void AttributeChecker::visitExtractConstantsFromMembersAttr(ExtractConstantsFromMembersAttr *attr) {
436+
if (!Ctx.LangOpts.hasFeature(Feature::ExtractConstantsFromMembers)) {
437+
diagnoseAndRemoveAttr(attr,
438+
diag::attr_extractConstantsFromMembers_experimental);
439+
}
440+
}
441+
433442
void AttributeChecker::visitTransparentAttr(TransparentAttr *attr) {
434443
DeclContext *dc = D->getDeclContext();
435444
// Protocol declarations cannot be transparent.

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,6 +1622,7 @@ namespace {
16221622
UNINTERESTING_ATTR(UnsafeInheritExecutor)
16231623
UNINTERESTING_ATTR(CompilerInitialized)
16241624
UNINTERESTING_ATTR(AlwaysEmitConformanceMetadata)
1625+
UNINTERESTING_ATTR(ExtractConstantsFromMembers)
16251626

16261627
UNINTERESTING_ATTR(EagerMove)
16271628
UNINTERESTING_ATTR(NoEagerMove)

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 820; // begin_borrow/move_value [var_decl]
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 821; // extractConstantsFromMembers
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: echo "[]" > %t/protocols.json
3+
4+
// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractConstantsFromMembersAttribute.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s -enable-experimental-feature ExtractConstantsFromMembers
5+
// RUN: cat %t/ExtractConstantsFromMembersAttribute.swiftconstvalues 2>&1 | %FileCheck %s
6+
7+
@extractConstantsFromMembers protocol MyProto {}
8+
public struct TestStruct : MyProto {
9+
let foo = "foo"
10+
let cane: [String] = ["bar", "baz"]
11+
}
12+
13+
// CHECK: "label": "foo",
14+
// CHECK: "valueKind": "RawLiteral",
15+
// CHECK: "value": "foo"
16+
17+
// CHECK: "label": "cane",
18+
// CHECK-NEXT: "type": "Swift.Array<Swift.String>",
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// RUN: %target-typecheck-verify-swift %s
2+
3+
// expected-error@+1{{@extractConstantsFromMembers requires '-enable-experimental-feature ExtractConstantsFromMembers'}}
4+
@extractConstantsFromMembers protocol MyProto {}

0 commit comments

Comments
 (0)