Skip to content

Commit df95779

Browse files
authored
Merge pull request #68852 from hborla/5.10-sendable-fixes
[5.10][Concurrency] An assortment of bug fixes in `Sendable` and actor isolation checking.
2 parents 3c3ade3 + 457e34a commit df95779

28 files changed

+362
-440
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 31 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,6 @@ class NominalTypeDecl;
3131
class SubstitutionMap;
3232
class AbstractFunctionDecl;
3333
class AbstractClosureExpr;
34-
class ClosureActorIsolation;
35-
36-
/// Trampoline for AbstractClosureExpr::getActorIsolation.
37-
ClosureActorIsolation
38-
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);
39-
40-
/// Returns a function reference to \c __AbstractClosureExpr_getActorIsolation.
41-
/// This is needed so we can use it as a default argument for
42-
/// \c getActorIsolationOfContext without knowing the layout of
43-
/// \c ClosureActorIsolation.
44-
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
45-
_getRef__AbstractClosureExpr_getActorIsolation();
4634

4735
/// Determine whether the given types are (canonically) equal, declared here
4836
/// to avoid having to include Types.h.
@@ -68,10 +56,10 @@ class ActorIsolation {
6856
/// For example, a mutable stored property or synchronous function within
6957
/// the actor is isolated to the instance of that actor.
7058
ActorInstance,
71-
/// The declaration is explicitly specified to be independent of any actor,
59+
/// The declaration is explicitly specified to be not isolated to any actor,
7260
/// meaning that it can be used from any actor but is also unable to
7361
/// refer to the isolated state of any given actor.
74-
Independent,
62+
Nonisolated,
7563
/// The declaration is isolated to a global actor. It can refer to other
7664
/// entities with the same global actor.
7765
GlobalActor,
@@ -83,29 +71,34 @@ class ActorIsolation {
8371

8472
private:
8573
union {
86-
NominalTypeDecl *actor;
74+
llvm::PointerUnion<NominalTypeDecl *, VarDecl *> actorInstance;
8775
Type globalActor;
8876
void *pointer;
8977
};
9078
unsigned kind : 3;
9179
unsigned isolatedByPreconcurrency : 1;
9280
unsigned parameterIndex : 28;
9381

94-
ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex)
95-
: actor(actor), kind(kind), isolatedByPreconcurrency(false),
96-
parameterIndex(parameterIndex) { }
82+
ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex);
83+
84+
ActorIsolation(Kind kind, VarDecl *capturedActor);
9785

9886
ActorIsolation(Kind kind, Type globalActor)
9987
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false),
10088
parameterIndex(0) { }
10189

10290
public:
91+
// No-argument constructor needed for DenseMap use in PostfixCompletion.cpp
92+
explicit ActorIsolation(Kind kind = Unspecified)
93+
: pointer(nullptr), kind(kind), isolatedByPreconcurrency(false),
94+
parameterIndex(0) { }
95+
10396
static ActorIsolation forUnspecified() {
10497
return ActorIsolation(Unspecified, nullptr);
10598
}
10699

107-
static ActorIsolation forIndependent() {
108-
return ActorIsolation(Independent, nullptr);
100+
static ActorIsolation forNonisolated() {
101+
return ActorIsolation(Nonisolated, nullptr);
109102
}
110103

111104
static ActorIsolation forActorInstanceSelf(NominalTypeDecl *actor) {
@@ -117,6 +110,10 @@ class ActorIsolation {
117110
return ActorIsolation(ActorInstance, actor, parameterIndex + 1);
118111
}
119112

113+
static ActorIsolation forActorInstanceCapture(VarDecl *capturedActor) {
114+
return ActorIsolation(ActorInstance, capturedActor);
115+
}
116+
120117
static ActorIsolation forGlobalActor(Type globalActor, bool unsafe) {
121118
return ActorIsolation(
122119
unsafe ? GlobalActorUnsafe : GlobalActor, globalActor);
@@ -128,7 +125,7 @@ class ActorIsolation {
128125

129126
bool isUnspecified() const { return kind == Unspecified; }
130127

131-
bool isIndependent() const { return kind == Independent; }
128+
bool isNonisolated() const { return kind == Nonisolated; }
132129

133130
/// Retrieve the parameter to which actor-instance isolation applies.
134131
///
@@ -146,15 +143,14 @@ class ActorIsolation {
146143
return true;
147144

148145
case Unspecified:
149-
case Independent:
146+
case Nonisolated:
150147
return false;
151148
}
152149
}
153150

154-
NominalTypeDecl *getActor() const {
155-
assert(getKind() == ActorInstance);
156-
return actor;
157-
}
151+
NominalTypeDecl *getActor() const;
152+
153+
VarDecl *getActorInstance() const;
158154

159155
bool isGlobalActor() const {
160156
return getKind() == GlobalActor || getKind() == GlobalActorUnsafe;
@@ -195,12 +191,13 @@ class ActorIsolation {
195191
return false;
196192

197193
switch (lhs.getKind()) {
198-
case Independent:
194+
case Nonisolated:
199195
case Unspecified:
200196
return true;
201197

202198
case ActorInstance:
203-
return lhs.actor == rhs.actor && lhs.parameterIndex == rhs.parameterIndex;
199+
return (lhs.getActor() == rhs.getActor() &&
200+
lhs.parameterIndex == rhs.parameterIndex);
204201

205202
case GlobalActor:
206203
case GlobalActorUnsafe:
@@ -223,43 +220,26 @@ class ActorIsolation {
223220
/// Determine how the given value declaration is isolated.
224221
ActorIsolation getActorIsolation(ValueDecl *value);
225222

223+
/// Trampoline for AbstractClosureExpr::getActorIsolation.
224+
ActorIsolation
225+
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);
226+
226227
/// Determine how the given declaration context is isolated.
227228
/// \p getClosureActorIsolation allows the specification of actor isolation for
228229
/// closures that haven't been saved been saved to the AST yet. This is useful
229230
/// for solver-based code completion which doesn't modify the AST but stores the
230231
/// actor isolation of closures in the constraint system solution.
231232
ActorIsolation getActorIsolationOfContext(
232233
DeclContext *dc,
233-
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
234-
getClosureActorIsolation =
235-
_getRef__AbstractClosureExpr_getActorIsolation());
234+
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
235+
getClosureActorIsolation = __AbstractClosureExpr_getActorIsolation);
236236

237237
/// Check if both the value, and context are isolated to the same actor.
238238
bool isSameActorIsolated(ValueDecl *value, DeclContext *dc);
239239

240240
/// Determines whether this function's body uses flow-sensitive isolation.
241241
bool usesFlowSensitiveIsolation(AbstractFunctionDecl const *fn);
242242

243-
/// Check if it is safe for the \c globalActor qualifier to be removed from
244-
/// \c ty, when the function value of that type is isolated to that actor.
245-
///
246-
/// In general this is safe in a narrow but common case: a global actor
247-
/// qualifier can be dropped from a function type while in a DeclContext
248-
/// isolated to that same actor, as long as the value is not Sendable.
249-
///
250-
/// \param dc the innermost context in which the cast to remove the global actor
251-
/// is happening.
252-
/// \param globalActor global actor that was dropped from \c ty.
253-
/// \param ty a function type where \c globalActor was removed from it.
254-
/// \param getClosureActorIsolation function that knows how to produce accurate
255-
/// information about the isolation of a closure.
256-
/// \return true if it is safe to drop the global-actor qualifier.
257-
bool safeToDropGlobalActor(
258-
DeclContext *dc, Type globalActor, Type ty,
259-
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
260-
getClosureActorIsolation =
261-
_getRef__AbstractClosureExpr_getActorIsolation());
262-
263243
void simple_display(llvm::raw_ostream &out, const ActorIsolation &state);
264244

265245
} // end namespace swift

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5236,8 +5236,9 @@ ERROR(concurrent_access_of_inout_param,none,
52365236
"concurrently-executing code",
52375237
(DeclName))
52385238
ERROR(non_sendable_capture,none,
5239-
"capture of %1 with non-sendable type %0 in a `@Sendable` closure",
5240-
(Type, DeclName))
5239+
"capture of %1 with non-sendable type %0 in a `@Sendable` "
5240+
"%select{local function|closure}2",
5241+
(Type, DeclName, bool))
52415242
ERROR(implicit_async_let_non_sendable_capture,none,
52425243
"capture of %1 with non-sendable type %0 in 'async let' binding",
52435244
(Type, DeclName))

include/swift/AST/Expr.h

Lines changed: 7 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,92 +3774,6 @@ class SequenceExpr final : public Expr,
37743774
}
37753775
};
37763776

3777-
/// Actor isolation for a closure.
3778-
class ClosureActorIsolation {
3779-
public:
3780-
enum Kind {
3781-
/// The closure is independent of any actor.
3782-
Independent,
3783-
3784-
/// The closure is tied to the actor instance described by the given
3785-
/// \c VarDecl*, which is the (captured) `self` of an actor.
3786-
ActorInstance,
3787-
3788-
/// The closure is tied to the global actor described by the given type.
3789-
GlobalActor,
3790-
};
3791-
3792-
private:
3793-
/// The actor to which this closure is isolated, plus a bit indicating
3794-
/// whether the isolation was imposed by a preconcurrency declaration.
3795-
///
3796-
/// There are three possible states for the pointer:
3797-
/// - NULL: The closure is independent of any actor.
3798-
/// - VarDecl*: The 'self' variable for the actor instance to which
3799-
/// this closure is isolated. It will always have a type that conforms
3800-
/// to the \c Actor protocol.
3801-
/// - Type: The type of the global actor on which
3802-
llvm::PointerIntPair<llvm::PointerUnion<VarDecl *, Type>, 1, bool> storage;
3803-
3804-
ClosureActorIsolation(VarDecl *selfDecl, bool preconcurrency)
3805-
: storage(selfDecl, preconcurrency) { }
3806-
ClosureActorIsolation(Type globalActorType, bool preconcurrency)
3807-
: storage(globalActorType, preconcurrency) { }
3808-
3809-
public:
3810-
ClosureActorIsolation(bool preconcurrency = false)
3811-
: storage(nullptr, preconcurrency) { }
3812-
3813-
static ClosureActorIsolation forIndependent(bool preconcurrency) {
3814-
return ClosureActorIsolation(preconcurrency);
3815-
}
3816-
3817-
static ClosureActorIsolation forActorInstance(VarDecl *selfDecl,
3818-
bool preconcurrency) {
3819-
return ClosureActorIsolation(selfDecl, preconcurrency);
3820-
}
3821-
3822-
static ClosureActorIsolation forGlobalActor(Type globalActorType,
3823-
bool preconcurrency) {
3824-
return ClosureActorIsolation(globalActorType, preconcurrency);
3825-
}
3826-
3827-
/// Determine the kind of isolation.
3828-
Kind getKind() const {
3829-
if (storage.getPointer().isNull())
3830-
return Kind::Independent;
3831-
3832-
if (storage.getPointer().is<VarDecl *>())
3833-
return Kind::ActorInstance;
3834-
3835-
return Kind::GlobalActor;
3836-
}
3837-
3838-
/// Whether the closure is isolated at all.
3839-
explicit operator bool() const {
3840-
return getKind() != Kind::Independent;
3841-
}
3842-
3843-
/// Whether the closure is isolated at all.
3844-
operator Kind() const {
3845-
return getKind();
3846-
}
3847-
3848-
VarDecl *getActorInstance() const {
3849-
return storage.getPointer().dyn_cast<VarDecl *>();
3850-
}
3851-
3852-
Type getGlobalActor() const {
3853-
return storage.getPointer().dyn_cast<Type>();
3854-
}
3855-
3856-
bool preconcurrency() const {
3857-
return storage.getInt();
3858-
}
3859-
3860-
ActorIsolation getActorIsolation() const;
3861-
};
3862-
38633777
/// A base class for closure expressions.
38643778
class AbstractClosureExpr : public DeclContext, public Expr {
38653779
CaptureInfo Captures;
@@ -3868,14 +3782,15 @@ class AbstractClosureExpr : public DeclContext, public Expr {
38683782
ParameterList *parameterList;
38693783

38703784
/// Actor isolation of the closure.
3871-
ClosureActorIsolation actorIsolation;
3785+
ActorIsolation actorIsolation;
38723786

38733787
public:
38743788
AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
38753789
DeclContext *Parent)
38763790
: DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
38773791
Expr(Kind, Implicit, FnType),
3878-
parameterList(nullptr) {
3792+
parameterList(nullptr),
3793+
actorIsolation(ActorIsolation::forUnspecified()) {
38793794
Bits.AbstractClosureExpr.Discriminator = InvalidDiscriminator;
38803795
}
38813796

@@ -3948,9 +3863,11 @@ class AbstractClosureExpr : public DeclContext, public Expr {
39483863
/// returns nullptr if the closure doesn't have a body
39493864
BraceStmt *getBody() const;
39503865

3951-
ClosureActorIsolation getActorIsolation() const { return actorIsolation; }
3866+
ActorIsolation getActorIsolation() const {
3867+
return actorIsolation;
3868+
}
39523869

3953-
void setActorIsolation(ClosureActorIsolation actorIsolation) {
3870+
void setActorIsolation(ActorIsolation actorIsolation) {
39543871
this->actorIsolation = actorIsolation;
39553872
}
39563873

include/swift/IDE/CompletionLookup.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
131131
bool CanCurrDeclContextHandleAsync = false;
132132
/// Actor isolations that were determined during constraint solving but that
133133
/// haven't been saved to the AST.
134-
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
134+
llvm::DenseMap<AbstractClosureExpr *, ActorIsolation>
135135
ClosureActorIsolations;
136136
bool HaveDot = false;
137137
bool IsUnwrappedOptional = false;
@@ -253,7 +253,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
253253
}
254254

255255
void setClosureActorIsolations(
256-
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
256+
llvm::DenseMap<AbstractClosureExpr *, ActorIsolation>
257257
ClosureActorIsolations) {
258258
this->ClosureActorIsolations = ClosureActorIsolations;
259259
}

include/swift/IDE/PostfixCompletion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback {
6363

6464
/// Actor isolations that were determined during constraint solving but that
6565
/// haven't been saved to the AST.
66-
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
66+
llvm::DenseMap<AbstractClosureExpr *, ActorIsolation>
6767
ClosureActorIsolations;
6868

6969
/// Checks whether this result has the same \c BaseTy and \c BaseDecl as

include/swift/Sema/IDETypeChecking.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,9 @@ namespace swift {
318318
bool completionContextUsesConcurrencyFeatures(const DeclContext *dc);
319319

320320
/// Determine the isolation of a particular closure.
321-
ClosureActorIsolation determineClosureActorIsolation(
321+
ActorIsolation determineClosureActorIsolation(
322322
AbstractClosureExpr *closure, llvm::function_ref<Type(Expr *)> getType,
323-
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
323+
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
324324
getClosureActorIsolation);
325325

326326
/// If the capture list shadows any declarations using shorthand syntax, i.e.

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2593,15 +2593,17 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25932593
<< " discriminator=" << E->getRawDiscriminator();
25942594

25952595
switch (auto isolation = E->getActorIsolation()) {
2596-
case ClosureActorIsolation::Independent:
2596+
case ActorIsolation::Unspecified:
2597+
case ActorIsolation::Nonisolated:
25972598
break;
25982599

2599-
case ClosureActorIsolation::ActorInstance:
2600+
case ActorIsolation::ActorInstance:
26002601
PrintWithColorRAII(OS, CapturesColor) << " actor-isolated="
26012602
<< isolation.getActorInstance()->printRef();
26022603
break;
26032604

2604-
case ClosureActorIsolation::GlobalActor:
2605+
case ActorIsolation::GlobalActor:
2606+
case ActorIsolation::GlobalActorUnsafe:
26052607
PrintWithColorRAII(OS, CapturesColor) << " global-actor-isolated="
26062608
<< isolation.getGlobalActor().getString();
26072609
break;

0 commit comments

Comments
 (0)