Skip to content

Commit aa3e590

Browse files
authored
Merge pull request #34305 from DougGregor/concurrency-actor-isolation-serialization
[Concurrency] Proper serialization/interface printing for actor-isolation attributes
2 parents f960907 + 4032cd8 commit aa3e590

File tree

6 files changed

+108
-26
lines changed

6 files changed

+108
-26
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,9 +2687,13 @@ enum class CustomAttrTypeKind {
26872687
/// any contextual type parameters.
26882688
NonGeneric,
26892689

2690-
/// Property delegates have some funky rules, like allowing
2690+
/// Property wrappers have some funky rules, like allowing
26912691
/// unbound generic types.
2692-
PropertyDelegate,
2692+
PropertyWrapper,
2693+
2694+
/// Global actors are represented as custom type attributes. They don't
2695+
/// have any particularly interesting semantics.
2696+
GlobalActor,
26932697
};
26942698

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

lib/AST/TypeCheckRequests.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,8 +1467,12 @@ void swift::simple_display(llvm::raw_ostream &out, CustomAttrTypeKind value) {
14671467
out << "non-generic";
14681468
return;
14691469

1470-
case CustomAttrTypeKind::PropertyDelegate:
1471-
out << "property-delegate";
1470+
case CustomAttrTypeKind::PropertyWrapper:
1471+
out << "property-wrapper";
1472+
return;
1473+
1474+
case CustomAttrTypeKind::GlobalActor:
1475+
out << "global-actor";
14721476
return;
14731477
}
14741478
llvm_unreachable("bad kind");

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@
2525

2626
using namespace swift;
2727

28+
/// Determine whether it makes sense to infer an attribute in the given
29+
/// context.
30+
static bool shouldInferAttributeInContext(const DeclContext *dc) {
31+
auto sourceFile = dc->getParentSourceFile();
32+
if (!sourceFile)
33+
return false;
34+
35+
switch (sourceFile->Kind) {
36+
case SourceFileKind::Interface:
37+
case SourceFileKind::SIL:
38+
return false;
39+
40+
case SourceFileKind::Library:
41+
case SourceFileKind::Main:
42+
return true;
43+
}
44+
}
45+
2846
/// Check whether the @asyncHandler attribute can be applied to the given
2947
/// function declaration.
3048
///
@@ -108,7 +126,7 @@ bool IsAsyncHandlerRequest::evaluate(
108126
return true;
109127
}
110128

111-
if (!func->getASTContext().LangOpts.EnableExperimentalConcurrency)
129+
if (!shouldInferAttributeInContext(func->getDeclContext()))
112130
return false;
113131

114132
// Are we in a context where inference is possible?
@@ -1016,15 +1034,18 @@ static Optional<ActorIsolation> getIsolationFromAttributes(Decl *decl) {
10161034
// If the declaration is marked with a global actor, report it as being
10171035
// part of that global actor.
10181036
if (globalActorAttr) {
1019-
TypeResolutionOptions options(TypeResolverContext::None);
1020-
TypeResolution resolver = TypeResolution::forInterface(
1021-
decl->getInnermostDeclContext(), options, nullptr);
1022-
Type globalActorType = resolver.resolveType(
1023-
globalActorAttr->first->getTypeRepr(), nullptr);
1037+
ASTContext &ctx = decl->getASTContext();
1038+
auto dc = decl->getInnermostDeclContext();
1039+
Type globalActorType = evaluateOrDefault(
1040+
ctx.evaluator,
1041+
CustomAttrTypeRequest{
1042+
globalActorAttr->first, dc, CustomAttrTypeKind::GlobalActor},
1043+
Type());
10241044
if (!globalActorType || globalActorType->hasError())
10251045
return ActorIsolation::forUnspecified();
10261046

1027-
return ActorIsolation::forGlobalActor(globalActorType);
1047+
return ActorIsolation::forGlobalActor(
1048+
globalActorType->mapTypeOutOfContext());
10281049
}
10291050

10301051
llvm_unreachable("Forgot about an attribute?");
@@ -1138,23 +1159,32 @@ ActorIsolation ActorIsolationRequest::evaluate(
11381159
}
11391160

11401161
// Disable inference of actor attributes outside of normal Swift source files.
1141-
if (auto sourceFile = value->getDeclContext()->getParentSourceFile()) {
1142-
switch (sourceFile->Kind) {
1143-
case SourceFileKind::Interface:
1144-
case SourceFileKind::SIL:
1145-
return defaultIsolation;
1146-
1147-
case SourceFileKind::Library:
1148-
case SourceFileKind::Main:
1149-
// Attempt inference below.
1150-
break;
1151-
}
1152-
} else {
1162+
if (!shouldInferAttributeInContext(value->getDeclContext()))
11531163
return defaultIsolation;
1154-
}
11551164

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

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ Type AttachedPropertyWrapperTypeRequest::evaluate(Evaluator &evaluator,
512512
auto ty = evaluateOrDefault(
513513
evaluator,
514514
CustomAttrTypeRequest{customAttr, var->getDeclContext(),
515-
CustomAttrTypeKind::PropertyDelegate},
515+
CustomAttrTypeKind::PropertyWrapper},
516516
Type());
517517
if (!ty || ty->hasError()) {
518518
return ErrorType::get(var->getASTContext());

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3979,7 +3979,7 @@ Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr,
39793979

39803980
OpenUnboundGenericTypeFn unboundTyOpener = nullptr;
39813981
// Property delegates allow their type to be an unbound generic.
3982-
if (typeKind == CustomAttrTypeKind::PropertyDelegate) {
3982+
if (typeKind == CustomAttrTypeKind::PropertyWrapper) {
39833983
unboundTyOpener = [](auto unboundTy) {
39843984
// FIXME: Don't let unbound generic types
39853985
// escape type resolution. For now, just
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)