Skip to content

Commit a2c57d1

Browse files
committed
[concurrency] initial declaration of MainActor
Implementation is left as a TODO for now. Resolves rdar://72161578 Partially resolves rdar://72105129
1 parent f76645d commit a2c57d1

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

lib/Frontend/ModuleInterfaceSupport.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ class InheritedProtocolCollector {
414414
if (!printOptions.shouldPrint(nominal))
415415
return;
416416

417+
/// is this nominal specifically an 'actor class'?
418+
bool actorClass = false;
419+
if (auto klass = dyn_cast<ClassDecl>(nominal))
420+
actorClass = klass->isActor();
421+
417422
SmallPtrSet<ProtocolDecl *, 16> handledProtocols;
418423

419424
// First record all protocols that have already been handled.
@@ -438,6 +443,15 @@ class InheritedProtocolCollector {
438443
if (!handledProtocols.insert(inherited).second)
439444
return TypeWalker::Action::SkipChildren;
440445

446+
// If 'nominal' is an 'actor class', we do not synthesize its
447+
// conformance to the Actor protocol through a dummy extension.
448+
// There is a special restriction on the Actor protocol in that
449+
// it is only valid to conform to Actor on an 'actor class' decl,
450+
// not extensions of that 'actor class'.
451+
if (actorClass &&
452+
inherited->isSpecificProtocol(KnownProtocolKind::Actor))
453+
return TypeWalker::Action::Continue;
454+
441455
if (isPublicOrUsableFromInline(inherited) &&
442456
conformanceDeclaredInModule(M, nominal, inherited)) {
443457
protocolsToPrint.push_back({inherited, protoAndAvailability.second});

stdlib/public/Concurrency/Actor.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,17 @@ public func _defaultActorDestroy(_ actor: AnyObject)
3838
@_silgen_name("swift_defaultActor_enqueue")
3939
public func _defaultActorEnqueue(partialTask: PartialAsyncTask,
4040
actor: AnyObject)
41+
42+
/// A singleton actor whose executor is equivalent to
43+
/// \c DispatchQueue.main, which is the main dispatch queue.
44+
@globalActor public final class MainActor {
45+
public static let shared = _Impl()
46+
47+
public actor class _Impl {
48+
@actorIndependent
49+
public func enqueue(partialTask: PartialAsyncTask) {
50+
// TODO: implement this.
51+
_ = (nil as String?)! + "MainActor is not implemented yet."
52+
}
53+
}
54+
}

test/Concurrency/global_actor_inference.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ struct GenericGlobalActor<T> {
1818
static var shared: SomeActor { SomeActor() }
1919
}
2020

21+
// ----------------------------------------------------------------------
22+
// Check that MainActor exists
23+
// ----------------------------------------------------------------------
24+
25+
@MainActor protocol Aluminium {
26+
func method()
27+
}
28+
@MainActor class Copper {}
29+
@MainActor func iron() {}
30+
2131
// ----------------------------------------------------------------------
2232
// Global actor inference for protocols
2333
// ----------------------------------------------------------------------
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -typecheck -enable-library-evolution -enable-experimental-concurrency -emit-module-interface-path %t/Library.swiftinterface -module-name Library %s
3+
// RUN: %FileCheck --check-prefix CHECK-EXTENSION %s <%t/Library.swiftinterface
4+
// RUN: %FileCheck --check-prefix CHECK %s <%t/Library.swiftinterface
5+
6+
/// This test ensures that, when generating a swiftinterface file,
7+
/// the actor class decl itself is what may conform to the Actor protocol,
8+
/// and not via some extension. The requirement is due to the unique
9+
/// optimizations applied to the implementation of actors.
10+
11+
// CHECK-EXTENSION-NOT: extension {{.+}} : _Concurrency.Actor
12+
13+
// CHECK: actor public class PlainActorClass {
14+
public actor class PlainActorClass {
15+
@actorIndependent public func enqueue(partialTask: PartialAsyncTask) { }
16+
}
17+
18+
// CHECK: actor public class ExplicitActorClass : _Concurrency.Actor {
19+
public actor class ExplicitActorClass : Actor {
20+
@actorIndependent public func enqueue(partialTask: PartialAsyncTask) { }
21+
}
22+
23+
// CHECK: actor public class EmptyActorClass {
24+
public actor class EmptyActorClass {}
25+
26+
// CHECK: public protocol Cat : _Concurrency.Actor {
27+
public protocol Cat : Actor {
28+
func mew()
29+
}
30+
31+
// CHECK: actor public class HouseCat : Library.Cat {
32+
public actor class HouseCat : Cat {
33+
@asyncHandler public func mew() {}
34+
@actorIndependent public func enqueue(partialTask: PartialAsyncTask) { }
35+
}
36+
37+
// CHECK: public protocol ToothyMouth {
38+
public protocol ToothyMouth {
39+
func chew()
40+
}
41+
42+
// CHECK: actor public class Lion : Library.ToothyMouth, _Concurrency.Actor {
43+
public actor class Lion : ToothyMouth, Actor {
44+
@asyncHandler public func chew() {}
45+
@actorIndependent public func enqueue(partialTask: PartialAsyncTask) { }
46+
}

0 commit comments

Comments
 (0)