Skip to content

Commit 7b1a6e4

Browse files
authored
Merge pull request swiftlang#33998 from DougGregor/concurrency-actor-independent
[Concurrency] Introduce `@actorIndependent` attribute.
2 parents 3921871 + 2762405 commit 7b1a6e4

20 files changed

+451
-49
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18+
SWIFT_TYPEID(ActorIsolation)
1819
SWIFT_TYPEID(AncestryFlags)
1920
SWIFT_TYPEID(CtorInitializerKind)
2021
SWIFT_TYPEID(FunctionBuilderBodyPreCheck)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
namespace swift {
2424

2525
class AbstractFunctionDecl;
26+
class ActorIsolation;
2627
class BraceStmt;
2728
class ClosureExpr;
2829
class CodeCompletionCallbacksFactory;

include/swift/AST/ActorIsolation.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//===--- ActorIsolation.h - Actor isolation ---------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file provides a description of actor isolation state.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#ifndef SWIFT_AST_ACTORISOLATIONSTATE_H
17+
#define SWIFT_AST_ACTORISOLATIONSTATE_H
18+
19+
#include "llvm/ADT/Hashing.h"
20+
21+
namespace llvm {
22+
class raw_ostream;
23+
}
24+
25+
namespace swift {
26+
class ClassDecl;
27+
28+
/// Describes the actor isolation of a given declaration, which determines
29+
/// the actors with which it can interact.
30+
class ActorIsolation {
31+
public:
32+
enum Kind {
33+
/// The actor isolation has not been specified. It is assumed to be
34+
/// unsafe to interact with this declaration from any actor.
35+
Unspecified = 0,
36+
/// The declaration is isolated to the instance of an actor class.
37+
/// For example, a mutable stored property or synchronous function within
38+
/// the actor is isolated to the instance of that actor.
39+
ActorInstance,
40+
/// The declaration can refer to actor-isolated state, but can also be
41+
//// referenced from outside the actor.
42+
ActorPrivileged,
43+
/// The declaration is explicitly specified to be independent of any actor,
44+
/// meaning that it can be used from any actor but is also unable to
45+
/// refer to the isolated state of any given actor.
46+
Independent,
47+
};
48+
49+
private:
50+
Kind kind;
51+
ClassDecl *actor;
52+
53+
ActorIsolation(Kind kind, ClassDecl *actor) : kind(kind), actor(actor) { }
54+
55+
public:
56+
static ActorIsolation forUnspecified() {
57+
return ActorIsolation(Unspecified, nullptr);
58+
}
59+
60+
static ActorIsolation forIndependent() {
61+
return ActorIsolation(Independent, nullptr);
62+
}
63+
64+
static ActorIsolation forActorPrivileged(ClassDecl *actor) {
65+
return ActorIsolation(ActorPrivileged, actor);
66+
}
67+
68+
static ActorIsolation forActorInstance(ClassDecl *actor) {
69+
return ActorIsolation(ActorInstance, actor);
70+
}
71+
72+
Kind getKind() const { return kind; }
73+
74+
operator Kind() const { return getKind(); }
75+
76+
ClassDecl *getActor() const {
77+
assert(getKind() == ActorInstance || getKind() == ActorPrivileged);
78+
return actor;
79+
}
80+
81+
friend bool operator==(const ActorIsolation &lhs,
82+
const ActorIsolation &rhs) {
83+
if (lhs.kind != rhs.kind)
84+
return false;
85+
86+
switch (lhs.kind) {
87+
case Independent:
88+
case Unspecified:
89+
return true;
90+
91+
case ActorInstance:
92+
case ActorPrivileged:
93+
return lhs.actor == rhs.actor;
94+
}
95+
}
96+
97+
friend bool operator!=(const ActorIsolation &lhs,
98+
const ActorIsolation &rhs) {
99+
return !(lhs == rhs);
100+
}
101+
102+
friend llvm::hash_code hash_value(const ActorIsolation &state) {
103+
return llvm::hash_combine(state.kind, state.actor);
104+
}
105+
};
106+
107+
void simple_display(llvm::raw_ostream &out, const ActorIsolation &state);
108+
109+
} // end namespace swift
110+
111+
#endif /* SWIFT_AST_ACTORISOLATIONSTATE_H */

include/swift/AST/Attr.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ SIMPLE_DECL_ATTR(noDerivative, NoDerivative,
562562
100)
563563

564564
SIMPLE_DECL_ATTR(asyncHandler, AsyncHandler,
565-
OnFunc | UserInaccessible |
565+
OnFunc | ConcurrencyOnly |
566566
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
567567
101)
568568

@@ -572,6 +572,12 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
572572
APIBreakingToAdd | APIBreakingToRemove,
573573
102)
574574

575+
SIMPLE_DECL_ATTR(actorIndependent, ActorIndependent,
576+
OnFunc | OnVar | OnSubscript | ConcurrencyOnly |
577+
ABIStableToAdd | ABIStableToRemove |
578+
APIStableToAdd | APIBreakingToRemove,
579+
103)
580+
575581
#undef TYPE_ATTR
576582
#undef DECL_ATTR_ALIAS
577583
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,11 @@ ERROR(pound_available_package_description_not_allowed, none,
17481748
ERROR(availability_query_repeated_platform, none,
17491749
"version for '%0' already specified", (StringRef))
17501750

1751+
ERROR(attr_requires_concurrency,none,
1752+
"'%0' %select{attribute|modifier}1 is only valid when experimental "
1753+
"concurrency is enabled",
1754+
(StringRef, bool))
1755+
17511756
//------------------------------------------------------------------------------
17521757
// MARK: syntax parsing diagnostics
17531758
//------------------------------------------------------------------------------

include/swift/AST/DiagnosticsSema.def

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4106,9 +4106,6 @@ NOTE(protocol_witness_async_conflict,none,
41064106
ERROR(async_autoclosure_nonasync_function,none,
41074107
"'async' autoclosure parameter in a non-'async' function", ())
41084108

4109-
ERROR(asynchandler_attr_requires_concurrency,none,
4110-
"'@asyncHandler' is only valid when experimental concurrency is enabled",
4111-
())
41124109
ERROR(asynchandler_non_func,none,
41134110
"'@asyncHandler' can only be applied to functions",
41144111
())
@@ -4141,15 +4138,17 @@ ERROR(satisfy_async_objc,none,
41414138
ERROR(async_objc_dynamic_self,none,
41424139
"asynchronous method returning 'Self' cannot be '@objc'", ())
41434140

4144-
ERROR(actor_without_concurrency,none,
4145-
"'actor' classes require experimental concurrency support", ())
41464141
ERROR(actor_with_nonactor_superclass,none,
41474142
"actor class cannot inherit from non-actor class %0", (DeclName))
41484143

41494144
ERROR(actor_isolated_non_self_reference,none,
41504145
"actor-isolated %0 %1 can only be referenced "
41514146
"%select{inside the actor|on 'self'}2",
41524147
(DescriptiveDeclKind, DeclName, bool))
4148+
ERROR(actor_isolated_self_independent_context,none,
4149+
"actor-isolated %0 %1 can not be referenced from an "
4150+
"'@actorIndependent' context",
4151+
(DescriptiveDeclKind, DeclName))
41534152
WARNING(concurrent_access_local,none,
41544153
"local %0 %1 is unsafe to reference in code that may execute "
41554154
"concurrently",
@@ -4174,6 +4173,24 @@ NOTE(actor_isolated_witness_could_be_async_handler,none,
41744173
"did you mean to make it an asychronous handler?",
41754174
(DescriptiveDeclKind, DeclName))
41764175

4176+
ERROR(actorisolated_let,none,
4177+
"'@actorIsolated' is meaningless on 'let' declarations because "
4178+
"they are immutable",
4179+
())
4180+
ERROR(actorisolated_mutable_storage,none,
4181+
"'@actorIsolated' can not be applied to stored properties",
4182+
())
4183+
ERROR(actorisolated_local_var,none,
4184+
"'@actorIsolated' can not be applied to local variables",
4185+
())
4186+
ERROR(actorisolated_not_actor_member,none,
4187+
"'@actorIsolated' can only be applied to actor members and "
4188+
"global/static variables",
4189+
())
4190+
ERROR(actorisolated_not_actor_instance_member,none,
4191+
"'@actorIsolated' can only be applied to instance members of actors",
4192+
())
4193+
41774194
//------------------------------------------------------------------------------
41784195
// MARK: Type Check Types
41794196
//------------------------------------------------------------------------------

include/swift/AST/TypeCheckRequests.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef SWIFT_TYPE_CHECK_REQUESTS_H
1717
#define SWIFT_TYPE_CHECK_REQUESTS_H
1818

19+
#include "swift/AST/ActorIsolation.h"
1920
#include "swift/AST/AnyFunctionRef.h"
2021
#include "swift/AST/ASTTypeIDs.h"
2122
#include "swift/AST/GenericSignature.h"
@@ -817,6 +818,24 @@ class IsActorRequest :
817818
bool isCached() const { return true; }
818819
};
819820

821+
/// Determine the actor isolation for the given declaration.
822+
class ActorIsolationRequest :
823+
public SimpleRequest<ActorIsolationRequest,
824+
ActorIsolation(ValueDecl *),
825+
RequestFlags::Cached> {
826+
public:
827+
using SimpleRequest::SimpleRequest;
828+
829+
private:
830+
friend SimpleRequest;
831+
832+
ActorIsolation evaluate(Evaluator &evaluator, ValueDecl *value) const;
833+
834+
public:
835+
// Caching
836+
bool isCached() const { return true; }
837+
};
838+
820839
/// Request whether the storage has a mutating getter.
821840
class IsGetterMutatingRequest :
822841
public SimpleRequest<IsGetterMutatingRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ SWIFT_REQUEST(TypeChecker, IsAsyncHandlerRequest, bool(FuncDecl *),
8585
Cached, NoLocationInfo)
8686
SWIFT_REQUEST(TypeChecker, IsActorRequest, bool(ClassDecl *),
8787
Cached, NoLocationInfo)
88+
SWIFT_REQUEST(TypeChecker, ActorIsolationRequest,
89+
ActorIsolationState(ValueDecl *),
90+
Cached, NoLocationInfo)
8891
SWIFT_REQUEST(TypeChecker, FunctionOperatorRequest, OperatorDecl *(FuncDecl *),
8992
Cached, NoLocationInfo)
9093
SWIFT_REQUEST(NameLookup, GenericSignatureRequest,

lib/AST/TypeCheckRequests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,3 +1496,25 @@ void CustomAttrTypeRequest::cacheResult(Type value) const {
14961496
auto *attr = std::get<0>(getStorage());
14971497
attr->setType(value);
14981498
}
1499+
1500+
1501+
void swift::simple_display(
1502+
llvm::raw_ostream &out, const ActorIsolation &state) {
1503+
switch (state) {
1504+
case ActorIsolation::ActorInstance:
1505+
out << "actor-isolated to instance of " << state.getActor()->getName();
1506+
break;
1507+
1508+
case ActorIsolation::ActorPrivileged:
1509+
out << "actor-privileged to instance of " << state.getActor()->getName();
1510+
break;
1511+
1512+
case ActorIsolation::Independent:
1513+
out << "actor-independent";
1514+
break;
1515+
1516+
case ActorIsolation::Unspecified:
1517+
out << "unspecified actor isolation";
1518+
break;
1519+
}
1520+
}

lib/Parse/ParseDecl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,15 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
13941394
DiscardAttribute = true;
13951395
}
13961396

1397+
// If this attribute is only permitted when concurrency is enabled, reject it.
1398+
if (DeclAttribute::isConcurrencyOnly(DK) &&
1399+
!shouldParseExperimentalConcurrency()) {
1400+
diagnose(
1401+
Loc, diag::attr_requires_concurrency, AttrName,
1402+
DeclAttribute::isDeclModifier(DK));
1403+
DiscardAttribute = true;
1404+
}
1405+
13971406
if (Context.LangOpts.Target.isOSBinFormatCOFF()) {
13981407
if (DK == DAK_WeakLinked) {
13991408
diagnose(Loc, diag::attr_unsupported_on_target, AttrName,

0 commit comments

Comments
 (0)