Skip to content

Commit dee5356

Browse files
committed
[Concurrency] Add inferred actor-isolation attributes.
When we infer an actor-isolation attribute on a declaration, add an implicit attribute that will show up in the printed interface and get serialized. ... and clean up the type resolution logic for global actor attributes to make it use CustomAttrTypeRequest, so the result gets appropriately cached in CustomAttr for serialization.
1 parent 21a0696 commit dee5356

File tree

4 files changed

+82
-6
lines changed

4 files changed

+82
-6
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,6 +2696,10 @@ enum class CustomAttrTypeKind {
26962696
/// Property delegates have some funky rules, like allowing
26972697
/// unbound generic types.
26982698
PropertyDelegate,
2699+
2700+
/// Global actors are represented as custom type attributes. They don't
2701+
/// have any particularly interesting semantics.
2702+
GlobalActor,
26992703
};
27002704

27012705
void simple_display(llvm::raw_ostream &out, CustomAttrTypeKind value);

lib/AST/TypeCheckRequests.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,10 @@ void swift::simple_display(llvm::raw_ostream &out, CustomAttrTypeKind value) {
14301430
case CustomAttrTypeKind::PropertyDelegate:
14311431
out << "property-delegate";
14321432
return;
1433+
1434+
case CustomAttrTypeKind::GlobalActor:
1435+
out << "global-actor";
1436+
return;
14331437
}
14341438
llvm_unreachable("bad kind");
14351439
}

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,15 +1031,18 @@ static Optional<ActorIsolation> getIsolationFromAttributes(Decl *decl) {
10311031
// If the declaration is marked with a global actor, report it as being
10321032
// part of that global actor.
10331033
if (globalActorAttr) {
1034-
TypeResolutionOptions options(TypeResolverContext::None);
1035-
TypeResolution resolver = TypeResolution::forInterface(
1036-
decl->getInnermostDeclContext(), options, nullptr);
1037-
Type globalActorType = resolver.resolveType(
1038-
globalActorAttr->first->getTypeRepr(), nullptr);
1034+
ASTContext &ctx = decl->getASTContext();
1035+
auto dc = decl->getInnermostDeclContext();
1036+
Type globalActorType = evaluateOrDefault(
1037+
ctx.evaluator,
1038+
CustomAttrTypeRequest{
1039+
globalActorAttr->first, dc, CustomAttrTypeKind::GlobalActor},
1040+
Type());
10391041
if (!globalActorType || globalActorType->hasError())
10401042
return ActorIsolation::forUnspecified();
10411043

1042-
return ActorIsolation::forGlobalActor(globalActorType);
1044+
return ActorIsolation::forGlobalActor(
1045+
globalActorType->mapTypeOutOfContext());
10431046
}
10441047

10451048
llvm_unreachable("Forgot about an attribute?");
@@ -1158,6 +1161,27 @@ ActorIsolation ActorIsolationRequest::evaluate(
11581161

11591162
// Function used when returning an inferred isolation.
11601163
auto inferredIsolation = [&](ActorIsolation inferred) {
1164+
// Add an implicit attribute to capture the actor isolation that was
1165+
// inferred, so that (e.g.) it will be printed and serialized.
1166+
ASTContext &ctx = value->getASTContext();
1167+
switch (inferred) {
1168+
case ActorIsolation::Independent:
1169+
value->getAttrs().add(new (ctx) ActorIndependentAttr(true));
1170+
break;
1171+
1172+
case ActorIsolation::GlobalActor: {
1173+
auto typeExpr = TypeExpr::createImplicit(inferred.getGlobalActor(), ctx);
1174+
auto attr = CustomAttr::create(
1175+
ctx, SourceLoc(), typeExpr, /*implicit=*/true);
1176+
value->getAttrs().add(attr);
1177+
break;
1178+
}
1179+
1180+
case ActorIsolation::ActorInstance:
1181+
case ActorIsolation::Unspecified:
1182+
// Nothing to do.
1183+
break;
1184+
}
11611185
return inferred;
11621186
};
11631187

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule -emit-module-interface-path %t/Test.swiftinterface -module-name Test -enable-experimental-concurrency %s
3+
// RUN: %FileCheck %s --check-prefix FROMSOURCE --check-prefix CHECK < %t/Test.swiftinterface
4+
// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-module-interface-path %t/TestFromModule.swiftinterface -module-name Test -enable-experimental-concurrency
5+
// RUN: %FileCheck %s --check-prefix FROMMODULE --check-prefix CHECK < %t/TestFromModule.swiftinterface
6+
7+
// REQUIRES: concurrency
8+
import _Concurrency
9+
10+
// CHECK: actor public class SomeActor
11+
public actor class SomeActor {
12+
@actorIndependent func maine() { }
13+
}
14+
15+
// CHECK: @globalActor public struct SomeGlobalActor
16+
@globalActor
17+
public struct SomeGlobalActor {
18+
public static let shared = SomeActor()
19+
}
20+
21+
// CHECK: @{{(Test.)?}}SomeGlobalActor public protocol P1
22+
// CHECK-NEXT: @{{(Test.)?}}SomeGlobalActor func method()
23+
@SomeGlobalActor
24+
public protocol P1 {
25+
func method()
26+
}
27+
28+
// CHECK: class C1
29+
// CHECK-NEXT: @{{(Test.)?}}SomeGlobalActor public func method()
30+
public class C1: P1 {
31+
public func method() { }
32+
}
33+
34+
@SomeGlobalActor
35+
public class C2 { }
36+
37+
// CHECK: @{{(Test.)?}}SomeGlobalActor public class C2
38+
public class C3: C2 { }
39+
40+
// CHECK: actor public class SomeSubActor
41+
// CHECK-NEXT: @actorIndependent public func maine()
42+
public actor class SomeSubActor: SomeActor {
43+
override public func maine() { }
44+
}

0 commit comments

Comments
 (0)