Skip to content

Commit 8ad2e02

Browse files
committed
Sema: Allow @execution on storage declarations
1 parent d73402a commit 8ad2e02

File tree

6 files changed

+101
-18
lines changed

6 files changed

+101
-18
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ DECL_ATTR(abi, ABI,
862862
DECL_ATTR_FEATURE_REQUIREMENT(ABI, ABIAttribute)
863863

864864
DECL_ATTR(execution, Execution,
865-
OnFunc | OnConstructor,
865+
OnFunc | OnConstructor | OnSubscript | OnVar,
866866
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
867867
166)
868868
DECL_ATTR_FEATURE_REQUIREMENT(Execution, ExecutionAttribute)

lib/AST/FeatureSet.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,13 +466,13 @@ static bool usesFeatureBuiltinEmplaceTypedThrows(Decl *decl) {
466466
}
467467

468468
static bool usesFeatureExecutionAttribute(Decl *decl) {
469+
if (!DeclAttribute::canAttributeAppearOnDecl(DeclAttrKind::Execution, decl)) {
470+
return false;
471+
}
472+
469473
if (decl->getAttrs().hasAttribute<ExecutionAttr>())
470474
return true;
471475

472-
auto VD = dyn_cast<ValueDecl>(decl);
473-
if (!VD)
474-
return false;
475-
476476
auto hasExecutionAttr = [](TypeRepr *R) {
477477
if (!R)
478478
return false;
@@ -490,6 +490,8 @@ static bool usesFeatureExecutionAttribute(Decl *decl) {
490490
});
491491
};
492492

493+
auto *VD = cast<ValueDecl>(decl);
494+
493495
// Check if any parameters that have `@execution` attribute.
494496
if (auto *PL = VD->getParameterList()) {
495497
for (auto *P : *PL) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,20 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
257257

258258
public:
259259
void visitExecutionAttr(ExecutionAttr *attr) {
260-
auto *F = dyn_cast<AbstractFunctionDecl>(D);
261-
if (!F)
260+
auto *const decl = cast<ValueDecl>(D);
261+
262+
auto *const storage = dyn_cast<AbstractStorageDecl>(decl);
263+
if (storage && storage->hasStorage()) {
264+
diagnoseAndRemoveAttr(attr, diag::attr_not_on_stored_properties, attr);
262265
return;
266+
}
263267

264-
if (!F->hasAsync()) {
265-
diagnoseAndRemoveAttr(attr, diag::attr_execution_only_on_async, F);
268+
if (!decl->isAsync()) {
269+
diagnoseAndRemoveAttr(attr, diag::attr_execution_only_on_async, decl);
266270
return;
267271
}
268272

269-
auto parameters = F->getParameters();
273+
auto *parameters = decl->getParameterList();
270274
if (!parameters)
271275
return;
272276

@@ -278,7 +282,8 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
278282
// isolated parameters affect isolation of the function itself
279283
if (isa<IsolatedTypeRepr>(repr)) {
280284
diagnoseAndRemoveAttr(
281-
attr, diag::attr_execution_incompatible_isolated_parameter, F, P);
285+
attr, diag::attr_execution_incompatible_isolated_parameter, decl,
286+
P);
282287
return;
283288
}
284289

@@ -287,7 +292,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
287292
diagnoseAndRemoveAttr(
288293
attr,
289294
diag::attr_execution_incompatible_dynamically_isolated_parameter,
290-
F, P);
295+
decl, P);
291296
return;
292297
}
293298
}

test/IDE/complete_decl_attribute_feature_requirement.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
@#^ON_GLOBALVAR^# var globalVar
5555
// ON_GLOBALVAR: Begin completions
5656
// ON_GLOBALVAR_ENABLED-DAG: Keyword/None: abi[#Var Attribute#]; name=abi
57-
// ON_GLOBALVAR_ENABLED-NOT: Keyword/None: execution[#{{.*}} Attribute#]; name=execution
57+
// ON_GLOBALVAR_ENABLED-DAG: Keyword/None: execution[#Var Attribute#]; name=execution
5858
// ON_GLOBALVAR_DISABLED-NOT: Keyword/None: abi[#{{.*}} Attribute#]; name=abi
5959
// ON_GLOBALVAR_DISABLED-NOT: Keyword/None: execution[#{{.*}} Attribute#]; name=execution
6060
// ON_GLOBALVAR: End completions
@@ -71,11 +71,19 @@ struct _S {
7171
@#^ON_PROPERTY^# var foo
7272
// ON_PROPERTY: Begin completions
7373
// ON_PROPERTY_ENABLED-DAG: Keyword/None: abi[#Var Attribute#]; name=abi
74-
// ON_PROPERTY_ENABLED-NOT: Keyword/None: execution[#{{.*}} Attribute#]; name=execution
74+
// ON_PROPERTY_ENABLED-DAG: Keyword/None: execution[#Var Attribute#]; name=execution
7575
// ON_PROPERTY_DISABLED-NOT: Keyword/None: abi[#{{.*}} Attribute#]; name=abi
7676
// ON_PROPERTY_DISABLED-NOT: Keyword/None: execution[#{{.*}} Attribute#]; name=execution
7777
// ON_PROPERTY: End completions
7878

79+
@#^ON_SUBSCR^# subscript
80+
// ON_SUBSCR: Begin completions
81+
// ON_SUBSCR_ENABLED-DAG: Keyword/None: abi[#Declaration Attribute#]; name=abi
82+
// ON_SUBSCR_ENABLED-DAG: Keyword/None: execution[#Declaration Attribute#]; name=execution
83+
// ON_SUBSCR_DISABLED-NOT: Keyword/None: abi[#{{.*}} Attribute#]; name=abi
84+
// ON_SUBSCR_DISABLED-NOT: Keyword/None: execution[#{{.*}} Attribute#]; name=execution
85+
// ON_SUBSCR: End completions
86+
7987
@#^ON_METHOD^# private
8088
func foo()
8189
// ON_METHOD: Begin completions

test/ModuleInterface/execution_attr.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,37 @@ public struct Test {
3030
// CHECK-NEXT: public func other(_: () async -> Swift.Void)
3131
// CHECK-NEXT: #endif
3232
public func other(_: @execution(caller) () async -> Void) {}
33+
34+
// CHECK: #if compiler(>=5.3) && $ExecutionAttribute
35+
// CHECK-NEXT: @execution(caller) public var testOnVar: Swift.Int {
36+
// CHECK-NEXT: get async
37+
// CHECK-NEXT: }
38+
// CHECK-NEXT: #else
39+
// CHECK-NEXT: public var testOnVar: Swift.Int {
40+
// CHECK-NEXT: get async
41+
// CHECK-NEXT: }
42+
// CHECK-NEXT: #endif
43+
@execution(caller)
44+
public var testOnVar: Int {
45+
get async {
46+
42
47+
}
48+
}
49+
50+
// CHECK: #if compiler(>=5.3) && $ExecutionAttribute
51+
// CHECK-NEXT: @execution(caller) public subscript(onSubscript _: Swift.Int) -> Swift.Bool {
52+
// CHECK-NEXT: get async
53+
// CHECK-NEXT: }
54+
// CHECK-NEXT: #else
55+
// CHECK-NEXT: public subscript(onSubscript _: Swift.Int) -> Swift.Bool {
56+
// CHECK-NEXT: get async
57+
// CHECK-NEXT: }
58+
// CHECK-NEXT: #endif
59+
@execution(caller)
60+
public subscript(onSubscript _: Int) -> Bool {
61+
get async {
62+
false
63+
}
64+
}
3365
}
3466

test/attr/attr_execution.swift

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
@execution(concurrent) @execution(caller) func mutipleAttrs() async {}
99
// expected-error@-1 {{duplicate attribute}} expected-note@-1 {{attribute already specified here}}
1010

11+
do {
12+
@execution(caller) struct S {}
13+
// expected-error@-1 {{'@execution(caller)' attribute cannot be applied to this declaration}}
14+
15+
func f(@execution(caller) param: Int) {}
16+
// expected-error@-1 {{'@execution(caller)' attribute cannot be applied to this declaration}}
17+
}
18+
1119
@execution(concurrent) func nonAsync1() {}
1220
// expected-error@-1 {{cannot use '@execution' on non-async global function 'nonAsync1()'}}
1321

@@ -27,16 +35,29 @@ struct Test {
2735

2836
@execution(concurrent) func member() async {} // Ok
2937

30-
// expected-error@+1 {{'@execution(caller)' attribute cannot be applied to this declaration}}
31-
@execution(caller) subscript(a: Int) -> Bool {
38+
@execution(concurrent) var syncP: Int {
39+
// expected-error@-1 {{cannot use '@execution' on non-async property 'syncP'}}
40+
get {}
41+
}
42+
@execution(concurrent) var asyncP: Int {
43+
get async {}
44+
}
45+
46+
// expected-error@+1 {{cannot use '@execution' on non-async subscript 'subscript(sync:)'}}
47+
@execution(caller) subscript(sync _: Int) -> Bool {
3248
@execution(concurrent) get { false }
3349
// expected-error@-1 {{@execution(concurrent)' attribute cannot be applied to this declaration}}
3450
@execution(concurrent) set { }
3551
// expected-error@-1 {{@execution(concurrent)' attribute cannot be applied to this declaration}}
3652
}
53+
@execution(caller) subscript(async _: Int) -> Bool {
54+
get async {}
55+
}
3756

38-
@execution(caller) var x: Int
39-
// expected-error@-1 {{'@execution(caller)' attribute cannot be applied to this declaration}}
57+
@execution(caller) var storedVar: Int
58+
// expected-error@-1 {{'@execution(caller)' must not be used on stored properties}}
59+
@execution(caller) let storedLet: Int
60+
// expected-error@-1 {{'@execution(caller)' must not be used on stored properties}}
4061
}
4162

4263
do {
@@ -48,16 +69,31 @@ do {
4869

4970
do {
5071
@execution(caller) func local() async {} // Ok
72+
73+
protocol P {
74+
@execution(caller) var syncP: Int { get }
75+
// expected-error@-1 {{cannot use '@execution' on non-async property 'syncP'}}
76+
77+
@execution(caller) var asyncP: Int { get async }
78+
}
5179
}
5280

5381
struct TestAttributeCollisions {
5482
@execution(concurrent) nonisolated func testNonIsolated() async {}
5583

5684
@execution(concurrent) func test(arg: isolated MainActor) async {}
5785
// expected-error@-1 {{cannot use '@execution' on instance method 'test(arg:)' because it has an isolated parameter: 'arg'}}
86+
@execution(concurrent) subscript(test arg: isolated MainActor) -> Int {
87+
// expected-error@-1 {{cannot use '@execution' on subscript 'subscript(test:)' because it has an isolated parameter: 'arg'}}
88+
get async {}
89+
}
5890

5991
@execution(concurrent) func testIsolationAny(arg: @isolated(any) () -> Void) async {}
6092
// expected-error@-1 {{cannot use '@execution' on instance method 'testIsolationAny(arg:)' because it has a dynamically isolated parameter: 'arg'}}
93+
@execution(concurrent) subscript(testIsolationAny arg: @isolated(any) () -> Void) -> Int {
94+
// expected-error@-1 {{cannot use '@execution' on subscript 'subscript(testIsolationAny:)' because it has a dynamically isolated parameter: 'arg'}}
95+
get async {}
96+
}
6197

6298
@MainActor @execution(concurrent) func testGlobalActor() async {}
6399
// expected-warning @-1 {{instance method 'testGlobalActor()' has multiple actor-isolation attributes ('MainActor' and 'execution(concurrent)')}}

0 commit comments

Comments
 (0)