Skip to content

Commit 2704ab7

Browse files
committed
[AST/ASTGen] Introduce @concurrent attribute to replace @execution(concurrent) spelling
1 parent 1a3af5c commit 2704ab7

File tree

10 files changed

+61
-9
lines changed

10 files changed

+61
-9
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,13 @@ SIMPLE_DECL_ATTR(extensible, Extensible,
884884
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr,
885885
169)
886886

887-
LAST_DECL_ATTR(Extensible)
887+
SIMPLE_DECL_ATTR(concurrent, Concurrent,
888+
OnFunc | OnConstructor | OnSubscript | OnVar,
889+
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,
890+
170)
891+
DECL_ATTR_FEATURE_REQUIREMENT(Concurrent, ExecutionAttribute)
892+
893+
LAST_DECL_ATTR(Concurrent)
888894

889895
#undef DECL_ATTR_ALIAS
890896
#undef CONTEXTUAL_DECL_ATTR_ALIAS

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4926,6 +4926,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
49264926
TRIVIAL_ATTR_PRINTER(WarnUnqualifiedAccess, warn_unqualified_access)
49274927
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
49284928
TRIVIAL_ATTR_PRINTER(Extensible, extensible)
4929+
TRIVIAL_ATTR_PRINTER(Concurrent, concurrent)
49294930

49304931
#undef TRIVIAL_ATTR_PRINTER
49314932

lib/AST/Decl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8758,6 +8758,9 @@ void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC) const {
87588758

87598759
std::optional<ExecutionKind>
87608760
AbstractFunctionDecl::getExecutionBehavior() const {
8761+
if (getAttrs().hasAttribute<ConcurrentAttr>())
8762+
return ExecutionKind::Concurrent;
8763+
87618764
auto *attr = getAttrs().getAttribute<ExecutionAttr>();
87628765
if (!attr)
87638766
return {};

lib/AST/FeatureSet.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ static bool usesFeatureExecutionAttribute(Decl *decl) {
510510
if (decl->getAttrs().hasAttribute<ExecutionAttr>())
511511
return true;
512512

513+
if (decl->getAttrs().hasAttribute<ConcurrentAttr>())
514+
return true;
515+
513516
auto hasExecutionAttr = [](TypeRepr *R) {
514517
if (!R)
515518
return false;

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ extension ASTGenVisitor {
197197
return handle(self.generateSimpleDeclAttr(attribute: node, kind: .atReasync))
198198
case .rethrows:
199199
return handle(self.generateSimpleDeclAttr(attribute: node, kind: .atRethrows))
200+
case .concurrent:
201+
return handle(self.generateSimpleDeclAttr(attribute: node, kind: .concurrent))
200202
case .none where attrName == "_unavailableInEmbedded":
201203
return handle(self.generateUnavailableInEmbeddedAttr(attribute: node)?.asDeclAttribute)
202204

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,8 +1414,10 @@ FunctionType::ExtInfo ClosureEffectsRequest::evaluate(
14141414
bool async = expr->getAsyncLoc().isValid();
14151415
bool sendable = expr->getAttrs().hasAttribute<SendableAttr>();
14161416

1417-
// `@execution(...)` attribute is only valid on asynchronous function types.
1418-
if (expr->getAttrs().hasAttribute<ExecutionAttr>()) {
1417+
// `@execution(...)` and `@concurrent` attributes are only
1418+
// valid on asynchronous function types.
1419+
if (expr->getAttrs().hasAttribute<ExecutionAttr>() ||
1420+
expr->getAttrs().hasAttribute<ConcurrentAttr>()) {
14191421
async = true;
14201422
}
14211423

lib/Sema/TypeCheckAttr.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
198198
TypeChecker::checkDeclABIAttribute(D, attr);
199199
}
200200

201-
void visitExecutionAttr(ExecutionAttr *attr) {
201+
void checkExecutionBehaviorAttribute(DeclAttribute *attr) {
202202
auto *const decl = cast<ValueDecl>(D);
203203

204204
auto *const storage = dyn_cast<AbstractStorageDecl>(decl);
@@ -258,6 +258,22 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
258258
}
259259
}
260260

261+
void visitExecutionAttr(ExecutionAttr *attr) {
262+
checkExecutionBehaviorAttribute(attr);
263+
264+
if (auto *concurrentAttr = D->getAttrs().getAttribute<ConcurrentAttr>())
265+
diagnoseAndRemoveAttr(attr, diag::actor_isolation_multiple_attr_2, D,
266+
attr, concurrentAttr);
267+
}
268+
269+
void visitConcurrentAttr(ConcurrentAttr *attr) {
270+
checkExecutionBehaviorAttribute(attr);
271+
272+
if (auto *executionAttr = D->getAttrs().getAttribute<ExecutionAttr>())
273+
diagnoseAndRemoveAttr(attr, diag::actor_isolation_multiple_attr_2, D,
274+
attr, executionAttr);
275+
}
276+
261277
void visitAlignmentAttr(AlignmentAttr *attr) {
262278
// Alignment must be a power of two.
263279
auto value = attr->getValue();
@@ -4316,6 +4332,7 @@ static void checkGlobalActorAttr(
43164332
auto isolatedAttr = decl->getAttrs().getAttribute<IsolatedAttr>();
43174333
auto nonisolatedAttr = decl->getAttrs().getAttribute<NonisolatedAttr>();
43184334
auto executionAttr = decl->getAttrs().getAttribute<ExecutionAttr>();
4335+
auto concurrentAttr = decl->getAttrs().getAttribute<ConcurrentAttr>();
43194336

43204337
llvm::SmallVector<const DeclAttribute *, 2> attributes;
43214338

@@ -4330,7 +4347,9 @@ static void checkGlobalActorAttr(
43304347
if (executionAttr) {
43314348
attributes.push_back(executionAttr);
43324349
}
4333-
4350+
if (concurrentAttr) {
4351+
attributes.push_back(concurrentAttr);
4352+
}
43344353
if (attributes.size() == 1)
43354354
return;
43364355

@@ -8145,13 +8164,13 @@ class ClosureAttributeChecker
81458164
// Nothing else to check.
81468165
}
81478166

8148-
void visitExecutionAttr(ExecutionAttr *attr) {
8167+
void checkExecutionBehaviorAttribute(DeclAttribute *attr) {
81498168
if (!ctx.LangOpts.hasFeature(Feature::ExecutionAttribute)) {
81508169
visitDeclAttribute(attr);
81518170
return;
81528171
}
81538172

8154-
// `@execution(...)` implies `async`.
8173+
// execution behavior attribute implies `async`.
81558174
if (closure->hasExplicitResultType() &&
81568175
closure->getAsyncLoc().isInvalid()) {
81578176
ctx.Diags
@@ -8184,6 +8203,14 @@ class ClosureAttributeChecker
81848203
}
81858204
}
81868205

8206+
void visitExecutionAttr(ExecutionAttr *attr) {
8207+
checkExecutionBehaviorAttribute(attr);
8208+
}
8209+
8210+
void visitConcurrentAttr(ConcurrentAttr *attr) {
8211+
checkExecutionBehaviorAttribute(attr);
8212+
}
8213+
81878214
void visitNonisolatedAttr(NonisolatedAttr *attr) {
81888215
if (attr->isUnsafe() ||
81898216
!ctx.LangOpts.hasFeature(Feature::ClosureIsolation)) {

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4890,6 +4890,7 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
48904890
auto nonisolatedAttr = decl->getAttrs().getAttribute<NonisolatedAttr>();
48914891
auto globalActorAttr = decl->getGlobalActorAttr();
48924892
auto concurrentExecutionAttr = decl->getAttrs().getAttribute<ExecutionAttr>();
4893+
auto concurrentAttr = decl->getAttrs().getAttribute<ConcurrentAttr>();
48934894

48944895
// Remove implicit attributes if we only care about explicit ones.
48954896
if (onlyExplicit) {
@@ -4901,11 +4902,14 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
49014902
globalActorAttr = std::nullopt;
49024903
if (concurrentExecutionAttr && concurrentExecutionAttr->isImplicit())
49034904
concurrentExecutionAttr = nullptr;
4905+
if (concurrentAttr && concurrentAttr->isImplicit())
4906+
concurrentAttr = nullptr;
49044907
}
49054908

49064909
unsigned numIsolationAttrs =
49074910
(isolatedAttr ? 1 : 0) + (nonisolatedAttr ? 1 : 0) +
4908-
(globalActorAttr ? 1 : 0) + (concurrentExecutionAttr ? 1 : 0);
4911+
(globalActorAttr ? 1 : 0) + (concurrentExecutionAttr ? 1 : 0) +
4912+
(concurrentAttr ? 1 : 0);
49094913
if (numIsolationAttrs == 0) {
49104914
if (isa<DestructorDecl>(decl) && !decl->isImplicit()) {
49114915
return ActorIsolation::forNonisolated(false);
@@ -4930,6 +4934,9 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
49304934
}
49314935
}
49324936

4937+
if (concurrentAttr)
4938+
return ActorIsolation::forNonisolated(/*is unsafe*/ false);
4939+
49334940
// If the declaration is explicitly marked 'nonisolated', report it as
49344941
// independent.
49354942
if (nonisolatedAttr) {

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,7 @@ namespace {
15881588
UNINTERESTING_ATTR(Borrowed)
15891589
UNINTERESTING_ATTR(Borrowing)
15901590
UNINTERESTING_ATTR(CDecl)
1591+
UNINTERESTING_ATTR(Concurrent)
15911592
UNINTERESTING_ATTR(Consuming)
15921593
UNINTERESTING_ATTR(Documentation)
15931594
UNINTERESTING_ATTR(Dynamic)

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 = 938; // custom AvailabilityDomains
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 939; // @concurrent attribute
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

0 commit comments

Comments
 (0)