Skip to content

Commit 30e75d8

Browse files
authored
Merge pull request swiftlang#37160 from DougGregor/concurrency-cleanups-5.5
Actors + concurrency fixes
2 parents 06e0e11 + 3b610fd commit 30e75d8

22 files changed

+228
-254
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ CHANGELOG
2929
Swift 5.5
3030
---------
3131

32+
* [SE-0306][]:
33+
34+
Swift 5.5 includes support for actors, a new kind of type that isolates its instance data to protect it from concurrent access. Accesses to an actor's instance declarations from outside the must be asynchronous:
35+
36+
```swift
37+
actor Counter {
38+
var value = 0
39+
40+
func increment() {
41+
value = value + 1
42+
}
43+
}
44+
45+
func useCounter(counter: Counter) async {
46+
print(await counter.value) // interaction must be async
47+
await counter.increment() // interaction must be async
48+
}
49+
```
50+
3251
* The determination of whether a call to a `rethrows` function can throw now considers default arguments of `Optional` type.
3352

3453
In Swift 5.4, such default arguments were ignored entirely by `rethrows` checking. This meant that the following example was accepted:
@@ -8434,6 +8453,7 @@ Swift 1.0
84348453
[SE-0297]: <https://github.com/apple/swift-evolution/blob/main/proposals/0297-concurrency-objc.md>
84358454
[SE-0298]: <https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md>
84368455
[SE-0299]: <https://github.com/apple/swift-evolution/blob/main/proposals/0299-extend-generic-static-member-lookup.md>
8456+
[SE-0306]: <https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md>
84378457

84388458
[SR-75]: <https://bugs.swift.org/browse/SR-75>
84398459
[SR-106]: <https://bugs.swift.org/browse/SR-106>

include/swift/ABI/MetadataValues.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,7 @@ class JobFlags : public FlagSet<size_t> {
20012001
Task_IsChildTask = 24,
20022002
Task_IsFuture = 25,
20032003
Task_IsGroupChildTask = 26,
2004+
Task_IsContinuingAsyncTask = 27,
20042005
};
20052006

20062007
explicit JobFlags(size_t bits) : FlagSet(bits) {}
@@ -2030,6 +2031,9 @@ class JobFlags : public FlagSet<size_t> {
20302031
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsGroupChildTask,
20312032
task_isGroupChildTask,
20322033
task_setIsGroupChildTask)
2034+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsContinuingAsyncTask,
2035+
task_isContinuingAsyncTask,
2036+
task_setIsContinuingAsyncTask)
20332037
};
20342038

20352039
/// Kinds of task status record.

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4351,8 +4351,8 @@ NOTE(objc_ambiguous_async_convention_candidate,none,
43514351
ERROR(async_objc_dynamic_self,none,
43524352
"asynchronous method returning 'Self' cannot be '@objc'", ())
43534353

4354-
ERROR(actor_with_nonactor_superclass,none,
4355-
"actor cannot inherit from non-actor class %0", (DeclName))
4354+
ERROR(actor_inheritance,none,
4355+
"actor types do not support inheritance", ())
43564356

43574357
ERROR(actor_isolated_non_self_reference,none,
43584358
"actor-isolated %0 %1 can only be %select{referenced|mutated|used 'inout'}3 "

include/swift/Basic/Features.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
LANGUAGE_FEATURE(StaticAssert, 0, "#assert", langOpts.EnableExperimentalStaticAssert)
3838
LANGUAGE_FEATURE(AsyncAwait, 296, "async/await", true)
3939
LANGUAGE_FEATURE(MarkerProtocol, 0, "@_marker protocol", true)
40-
LANGUAGE_FEATURE(Actors, 0, "actors", langOpts.EnableExperimentalConcurrency)
40+
LANGUAGE_FEATURE(Actors, 0, "actors", true)
4141
LANGUAGE_FEATURE(ConcurrentFunctions, 0, "@concurrent functions", true)
4242
LANGUAGE_FEATURE(RethrowsProtocol, 0, "@rethrows protocol", true)
4343
LANGUAGE_FEATURE(GlobalActors, 0, "Global actors", langOpts.EnableExperimentalConcurrency)

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3604,7 +3604,7 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
36043604
if (Kind == DAK_Count)
36053605
break;
36063606

3607-
if (Kind == DAK_Actor && shouldParseExperimentalConcurrency()) {
3607+
if (Kind == DAK_Actor) {
36083608
// If the next token is a startOfSwiftDecl, we are part of the modifier
36093609
// list and should consume the actor token (e.g, actor public class Foo)
36103610
// otherwise, it's the decl keyword (e.g. actor Foo) and shouldn't be.
@@ -4075,8 +4075,7 @@ bool Parser::isStartOfSwiftDecl() {
40754075
return isStartOfSwiftDecl();
40764076
}
40774077

4078-
if (shouldParseExperimentalConcurrency() &&
4079-
Tok.isContextualKeyword("actor")) {
4078+
if (Tok.isContextualKeyword("actor")) {
40804079
if (Tok2.is(tok::identifier)) // actor Foo {}
40814080
return true;
40824081
BacktrackingScope Scope(*this);
@@ -4428,8 +4427,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
44284427
// Obvious nonsense.
44294428
default:
44304429

4431-
if (shouldParseExperimentalConcurrency() &&
4432-
Tok.isContextualKeyword("actor") && peekToken().is(tok::identifier)) {
4430+
if (Tok.isContextualKeyword("actor") && peekToken().is(tok::identifier)) {
44334431
Tok.setKind(tok::contextual_keyword);
44344432
DeclParsingContext.setCreateSyntax(SyntaxKind::ClassDecl);
44354433
DeclResult = parseDeclClass(Flags, Attributes);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -270,32 +270,8 @@ bool IsActorRequest::evaluate(
270270
if (!classDecl)
271271
return false;
272272

273-
bool isExplicitActor = classDecl->isExplicitActor() ||
274-
classDecl->getAttrs().getAttribute<ActorAttr>();
275-
276-
// If there is a superclass, we can infer actor-ness from it.
277-
if (auto superclassDecl = classDecl->getSuperclassDecl()) {
278-
// The superclass is an actor, so we are, too.
279-
if (superclassDecl->isActor())
280-
return true;
281-
282-
// The superclass is 'NSObject', which is known to have no state and no
283-
// superclass.
284-
if (superclassDecl->isNSObject() && isExplicitActor)
285-
return true;
286-
287-
// This class cannot be an actor; complain if the 'actor' modifier was
288-
// provided.
289-
if (isExplicitActor) {
290-
classDecl->diagnose(diag::actor_with_nonactor_superclass,
291-
superclassDecl->getName())
292-
.highlight(classDecl->getStartLoc());
293-
}
294-
295-
return false;
296-
}
297-
298-
return isExplicitActor;
273+
return classDecl->isExplicitActor() ||
274+
classDecl->getAttrs().getAttribute<ActorAttr>();
299275
}
300276

301277
bool IsDefaultActorRequest::evaluate(
@@ -305,21 +281,6 @@ bool IsDefaultActorRequest::evaluate(
305281
if (!classDecl->isActor())
306282
return false;
307283

308-
// If there is a superclass, and it's an actor, we defer
309-
// the decision to it.
310-
if (auto superclassDecl = classDecl->getSuperclassDecl()) {
311-
// If the superclass is an actor, we inherit its default-actor-ness.
312-
if (superclassDecl->isActor())
313-
return superclassDecl->isDefaultActor();
314-
315-
// If the superclass is not an actor, it can only be
316-
// a default actor if it's NSObject. (For now, other classes simply
317-
// can't be actors at all.) We don't need to diagnose this; we
318-
// should've done that already in isActor().
319-
if (!superclassDecl->isNSObject())
320-
return false;
321-
}
322-
323284
// If the class is resilient from the perspective of the module
324285
// module, it's not a default actor.
325286
if (classDecl->isForeign() || classDecl->isResilient(M, expansion))

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,6 +2314,14 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23142314
// Check for circular inheritance.
23152315
(void)CD->getSuperclassDecl();
23162316

2317+
if (auto superclass = CD->getSuperclassDecl()) {
2318+
// Actors cannot have superclasses, nor can they be superclasses.
2319+
if (CD->isActor() && !superclass->isNSObject())
2320+
CD->diagnose(diag::actor_inheritance);
2321+
else if (superclass->isActor())
2322+
CD->diagnose(diag::actor_inheritance);
2323+
}
2324+
23172325
// Force lowering of stored properties.
23182326
(void) CD->getStoredProperties();
23192327

stdlib/public/Concurrency/Actor.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,12 @@ static bool isExecutingOnMainThread() {
274274
}
275275

276276
JobPriority swift::swift_task_getCurrentThreadPriority() {
277-
if (isExecutingOnMainThread())
278-
return JobPriority::UserInitiated;
279-
280277
#if defined(__APPLE__)
281278
return static_cast<JobPriority>(qos_class_self());
282279
#else
280+
if (isExecutingOnMainThread())
281+
return JobPriority::UserInitiated;
282+
283283
return JobPriority::Unspecified;
284284
#endif
285285
}

0 commit comments

Comments
 (0)