Skip to content

Commit 0cd0cbc

Browse files
authored
Merge pull request #37794 from DougGregor/isolated-parameters
[SE-0313] Implement type system, ABI, and runtime support for isolated parameters
2 parents e65ae80 + 474aa2e commit 0cd0cbc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1085
-397
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ Types
611611
type-list ::= empty-list
612612

613613
// FIXME: Consider replacing 'h' with a two-char code
614-
list-type ::= type identifier? 'Yk'? 'z'? 'h'? 'n'? 'd'? // type with optional label, '@noDerivative', inout convention, shared convention, owned convention, and variadic specifier
614+
list-type ::= type identifier? 'Yk'? 'z'? 'h'? 'n'? 'Yi'? 'd'? // type with optional label, '@noDerivative', inout convention, shared convention, owned convention, actor 'isolated', and variadic specifier
615615

616616
METATYPE-REPR ::= 't' // Thin metatype representation
617617
METATYPE-REPR ::= 'T' // Thick metatype representation

include/swift/ABI/MetadataValues.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,8 @@ class TargetParameterTypeFlags {
950950
ValueOwnershipMask = 0x7F,
951951
VariadicMask = 0x80,
952952
AutoClosureMask = 0x100,
953-
NoDerivativeMask = 0x200
953+
NoDerivativeMask = 0x200,
954+
IsolatedMask = 0x400,
954955
};
955956
int_type Data;
956957

@@ -983,10 +984,17 @@ class TargetParameterTypeFlags {
983984
(Data & ~NoDerivativeMask) | (isNoDerivative ? NoDerivativeMask : 0));
984985
}
985986

987+
constexpr TargetParameterTypeFlags<int_type>
988+
withIsolated(bool isIsolated) const {
989+
return TargetParameterTypeFlags<int_type>(
990+
(Data & ~IsolatedMask) | (isIsolated ? IsolatedMask : 0));
991+
}
992+
986993
bool isNone() const { return Data == 0; }
987994
bool isVariadic() const { return Data & VariadicMask; }
988995
bool isAutoClosure() const { return Data & AutoClosureMask; }
989996
bool isNoDerivative() const { return Data & NoDerivativeMask; }
997+
bool isIsolated() const { return Data & IsolatedMask; }
990998

991999
ValueOwnership getValueOwnership() const {
9921000
return (ValueOwnership)(Data & ValueOwnershipMask);

include/swift/AST/Attr.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,11 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
574574
APIBreakingToAdd | APIBreakingToRemove,
575575
102)
576576

577-
// Unused attribute 103
577+
CONTEXTUAL_SIMPLE_DECL_ATTR(isolated, Isolated,
578+
DeclModifier | OnParam |
579+
ABIBreakingToAdd | ABIBreakingToRemove |
580+
APIBreakingToAdd | APIBreakingToRemove,
581+
103)
578582

579583
SIMPLE_DECL_ATTR(globalActor, GlobalActor,
580584
OnClass | OnStruct | OnEnum | ConcurrencyOnly |
@@ -668,7 +672,6 @@ SIMPLE_DECL_ATTR(_distributedActorIndependent, DistributedActorIndependent,
668672
APIBreakingToAdd | APIBreakingToRemove,
669673
119)
670674

671-
672675
#undef TYPE_ATTR
673676
#undef DECL_ATTR_ALIAS
674677
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/Decl.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5262,7 +5262,7 @@ class ParamDecl : public VarDecl {
52625262

52635263
TypeRepr *TyRepr = nullptr;
52645264

5265-
struct StoredDefaultArgument {
5265+
struct alignas(1 << DeclAlignInBits) StoredDefaultArgument {
52665266
PointerUnion<Expr *, VarDecl *> DefaultArg;
52675267

52685268
/// Stores the context for the default argument as well as a bit to
@@ -5283,10 +5283,13 @@ class ParamDecl : public VarDecl {
52835283

52845284
/// Whether or not this parameter is `@autoclosure`.
52855285
IsAutoClosure = 1 << 1,
5286+
5287+
/// Whether or not this parameter is 'isolated'.
5288+
IsIsolated = 1 << 2,
52865289
};
52875290

52885291
/// The default value, if any, along with flags.
5289-
llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>>
5292+
llvm::PointerIntPair<StoredDefaultArgument *, 3, OptionSet<Flags>>
52905293
DefaultValueAndFlags;
52915294

52925295
friend class ParamSpecifierRequest;
@@ -5440,6 +5443,17 @@ class ParamDecl : public VarDecl {
54405443
: flags - Flags::IsAutoClosure);
54415444
}
54425445

5446+
/// Whether or not this parameter is marked with 'isolated'.
5447+
bool isIsolated() const {
5448+
return DefaultValueAndFlags.getInt().contains(Flags::IsIsolated);
5449+
}
5450+
5451+
void setIsolated(bool value = true) {
5452+
auto flags = DefaultValueAndFlags.getInt();
5453+
DefaultValueAndFlags.setInt(value ? flags | Flags::IsIsolated
5454+
: flags - Flags::IsIsolated);
5455+
}
5456+
54435457
/// Does this parameter reject temporary pointer conversions?
54445458
bool isNonEphemeral() const;
54455459

include/swift/AST/DiagnosticsSema.def

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4349,31 +4349,27 @@ ERROR(override_implicit_unowned_executor,none,
43494349
"explicitly defined", ())
43504350

43514351
ERROR(actor_isolated_non_self_reference,none,
4352-
"actor-isolated %0 %1 can only be %select{referenced|mutated|used 'inout'}3 "
4353-
"%select{from inside the actor|on 'self'}2",
4354-
(DescriptiveDeclKind, DeclName, bool, unsigned))
4352+
"actor-isolated %0 %1 can not be "
4353+
"%select{referenced|mutated|used 'inout'}2 "
4354+
"%select{on a non-isolated actor instance|"
4355+
"from a Sendable function|from a Sendable closure|"
4356+
"from an 'async let' initializer|from global actor %4|"
4357+
"from the main actor|from a non-isolated context}3",
4358+
(DescriptiveDeclKind, DeclName, unsigned, unsigned, Type))
43554359
ERROR(distributed_actor_isolated_non_self_reference,none,
43564360
"distributed actor-isolated %0 %1 can only be referenced "
43574361
"inside the distributed actor",
43584362
(DescriptiveDeclKind, DeclName))
43594363
ERROR(distributed_actor_needs_explicit_distributed_import,none,
43604364
"'_Distributed' module not imported, required for 'distributed actor'",
43614365
())
4362-
ERROR(actor_isolated_self_independent_context,none,
4363-
"actor-isolated %0 %1 can not be %select{referenced|mutated|used 'inout'}2 from a "
4364-
"non-isolated context",
4365-
(DescriptiveDeclKind, DeclName, unsigned))
43664366
ERROR(actor_isolated_inout_state,none,
43674367
"actor-isolated %0 %1 cannot be passed 'inout' to"
43684368
"%select{| implicitly}2 'async' function call",
43694369
(DescriptiveDeclKind, DeclName, bool))
43704370
ERROR(actor_isolated_mutating_func,none,
43714371
"cannot call mutating async function %0 on actor-isolated %1 %2",
43724372
(DeclName, DescriptiveDeclKind, DeclName))
4373-
ERROR(actor_isolated_global_actor_context,none,
4374-
"actor-isolated %0 %1 can not be %select{referenced|mutated|used 'inout'}3 "
4375-
"from%select{| synchronous}4 context of global actor %2",
4376-
(DescriptiveDeclKind, DeclName, Type, unsigned, bool))
43774373
ERROR(global_actor_from_instance_actor_context,none,
43784374
"%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4"
43794375
" from actor %3 %select{|in a synchronous context}5",
@@ -4398,15 +4394,6 @@ ERROR(actor_isolated_partial_apply,none,
43984394
ERROR(concurrent_access_local,none,
43994395
"use of local %0 %1 in concurrently-executing code",
44004396
(DescriptiveDeclKind, DeclName))
4401-
ERROR(actor_isolated_from_concurrent_closure,none,
4402-
"actor-isolated %0 %1 cannot be %select{referenced|mutated|used 'inout'}2 from a concurrent closure",
4403-
(DescriptiveDeclKind, DeclName, unsigned))
4404-
ERROR(actor_isolated_from_concurrent_function,none,
4405-
"actor-isolated %0 %1 cannot be %select{referenced|mutated|used 'inout'}2 from a concurrent function",
4406-
(DescriptiveDeclKind, DeclName, unsigned))
4407-
ERROR(actor_isolated_from_async_let,none,
4408-
"actor-isolated %0 %1 cannot be %select{referenced|mutated|used 'inout'}2 from 'async let' initializer",
4409-
(DescriptiveDeclKind, DeclName, unsigned))
44104397
ERROR(actor_isolated_keypath_component,none,
44114398
"cannot form key path to%select{| distributed}0 actor-isolated %1 %2",
44124399
(bool, DescriptiveDeclKind, DeclName))
@@ -4475,6 +4462,9 @@ ERROR(actor_cannot_conform_to_global_actor_protocol,none,
44754462
NOTE(protocol_isolated_to_global_actor_here,none,
44764463
"%0 is isolated to global actor %1 here", (Type, Type))
44774464

4465+
ERROR(isolated_parameter_not_actor,none,
4466+
"'isolated' parameter has non-actor type %0", (Type))
4467+
44784468
WARNING(non_concurrent_param_type,none,
44794469
"cannot pass argument of non-sendable type %0 across actors",
44804470
(Type))

include/swift/AST/TypeCheckRequests.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,20 @@ class ActorIsolationRequest :
10201020
bool isCached() const { return true; }
10211021
};
10221022

1023+
/// Determine whether the given function should have an isolated 'self'.
1024+
class HasIsolatedSelfRequest :
1025+
public SimpleRequest<HasIsolatedSelfRequest,
1026+
bool(ValueDecl *),
1027+
RequestFlags::Uncached> {
1028+
public:
1029+
using SimpleRequest::SimpleRequest;
1030+
1031+
private:
1032+
friend SimpleRequest;
1033+
1034+
bool evaluate(Evaluator &evaluator, ValueDecl *func) const;
1035+
};
1036+
10231037
/// Request whether the storage has a mutating getter.
10241038
class IsGetterMutatingRequest :
10251039
public SimpleRequest<IsGetterMutatingRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ SWIFT_REQUEST(TypeChecker, GlobalActorAttributeRequest,
114114
SWIFT_REQUEST(TypeChecker, ActorIsolationRequest,
115115
ActorIsolationState(ValueDecl *),
116116
Cached, NoLocationInfo)
117+
SWIFT_REQUEST(TypeChecker, HasIsolatedSelfRequest,
118+
bool(ValueDecl *),
119+
Uncached, NoLocationInfo)
117120
SWIFT_REQUEST(TypeChecker, FunctionOperatorRequest, OperatorDecl *(FuncDecl *),
118121
Cached, NoLocationInfo)
119122
SWIFT_REQUEST(NameLookup, GenericSignatureRequest,

include/swift/AST/TypeRepr.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,8 @@ class SpecifierTypeRepr : public TypeRepr {
939939
static bool classof(const TypeRepr *T) {
940940
return T->getKind() == TypeReprKind::InOut ||
941941
T->getKind() == TypeReprKind::Shared ||
942-
T->getKind() == TypeReprKind::Owned;
942+
T->getKind() == TypeReprKind::Owned ||
943+
T->getKind() == TypeReprKind::Isolated;
943944
}
944945
static bool classof(const SpecifierTypeRepr *T) { return true; }
945946

@@ -995,6 +996,21 @@ class OwnedTypeRepr : public SpecifierTypeRepr {
995996
static bool classof(const OwnedTypeRepr *T) { return true; }
996997
};
997998

999+
/// An 'isolated' type.
1000+
/// \code
1001+
/// x : isolated Actor
1002+
/// \endcode
1003+
class IsolatedTypeRepr : public SpecifierTypeRepr {
1004+
public:
1005+
IsolatedTypeRepr(TypeRepr *Base, SourceLoc InOutLoc)
1006+
: SpecifierTypeRepr(TypeReprKind::Isolated, Base, InOutLoc) {}
1007+
1008+
static bool classof(const TypeRepr *T) {
1009+
return T->getKind() == TypeReprKind::Isolated;
1010+
}
1011+
static bool classof(const IsolatedTypeRepr *T) { return true; }
1012+
};
1013+
9981014
/// A TypeRepr for a known, fixed type.
9991015
///
10001016
/// Fixed type representations should be used sparingly, in places
@@ -1226,6 +1242,7 @@ inline bool TypeRepr::isSimple() const {
12261242
case TypeReprKind::SILBox:
12271243
case TypeReprKind::Shared:
12281244
case TypeReprKind::Owned:
1245+
case TypeReprKind::Isolated:
12291246
case TypeReprKind::Placeholder:
12301247
return true;
12311248
}

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ ABSTRACT_TYPEREPR(Specifier, TypeRepr)
5959
TYPEREPR(InOut, SpecifierTypeRepr)
6060
TYPEREPR(Shared, SpecifierTypeRepr)
6161
TYPEREPR(Owned, SpecifierTypeRepr)
62+
TYPEREPR(Isolated, SpecifierTypeRepr)
6263
TYPEREPR(Fixed, TypeRepr)
6364
TYPEREPR(SILBox, TypeRepr)
6465
LAST_TYPEREPR(SILBox)

include/swift/AST/Types.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,10 +1929,11 @@ class ParameterTypeFlags {
19291929
OwnershipShift = 3,
19301930
Ownership = 7 << OwnershipShift,
19311931
NoDerivative = 1 << 6,
1932-
NumBits = 7
1932+
Isolated = 1 << 7,
1933+
NumBits = 8
19331934
};
19341935
OptionSet<ParameterFlags> value;
1935-
static_assert(NumBits < 8*sizeof(OptionSet<ParameterFlags>), "overflowed");
1936+
static_assert(NumBits <= 8*sizeof(OptionSet<ParameterFlags>), "overflowed");
19361937

19371938
ParameterTypeFlags(OptionSet<ParameterFlags, uint8_t> val) : value(val) {}
19381939

@@ -1943,17 +1944,18 @@ class ParameterTypeFlags {
19431944
}
19441945

19451946
ParameterTypeFlags(bool variadic, bool autoclosure, bool nonEphemeral,
1946-
ValueOwnership ownership, bool noDerivative)
1947+
ValueOwnership ownership, bool isolated, bool noDerivative)
19471948
: value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
19481949
(nonEphemeral ? NonEphemeral : 0) |
19491950
uint8_t(ownership) << OwnershipShift |
1951+
(isolated ? Isolated : 0) |
19501952
(noDerivative ? NoDerivative : 0)) {}
19511953

19521954
/// Create one from what's present in the parameter type
19531955
inline static ParameterTypeFlags
19541956
fromParameterType(Type paramTy, bool isVariadic, bool isAutoClosure,
19551957
bool isNonEphemeral, ValueOwnership ownership,
1956-
bool isNoDerivative);
1958+
bool isolated, bool isNoDerivative);
19571959

19581960
bool isNone() const { return !value; }
19591961
bool isVariadic() const { return value.contains(Variadic); }
@@ -1962,6 +1964,7 @@ class ParameterTypeFlags {
19621964
bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; }
19631965
bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
19641966
bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }
1967+
bool isIsolated() const { return value.contains(Isolated); }
19651968
bool isNoDerivative() const { return value.contains(NoDerivative); }
19661969

19671970
ValueOwnership getValueOwnership() const {
@@ -2005,6 +2008,12 @@ class ParameterTypeFlags {
20052008
: value - ParameterTypeFlags::NonEphemeral);
20062009
}
20072010

2011+
ParameterTypeFlags withIsolated(bool isolated) const {
2012+
return ParameterTypeFlags(isolated
2013+
? value | ParameterTypeFlags::Isolated
2014+
: value - ParameterTypeFlags::Isolated);
2015+
}
2016+
20082017
ParameterTypeFlags withNoDerivative(bool noDerivative) const {
20092018
return ParameterTypeFlags(noDerivative
20102019
? value | ParameterTypeFlags::NoDerivative
@@ -2078,7 +2087,7 @@ class YieldTypeFlags {
20782087
return ParameterTypeFlags(/*variadic*/ false,
20792088
/*autoclosure*/ false,
20802089
/*nonEphemeral*/ false, getValueOwnership(),
2081-
/*noDerivative*/ false);
2090+
/*isolated*/ false, /*noDerivative*/ false);
20822091
}
20832092

20842093
bool operator ==(const YieldTypeFlags &other) const {
@@ -2857,6 +2866,9 @@ class AnyFunctionType : public TypeBase {
28572866
/// Whether the parameter is marked '@_nonEphemeral'
28582867
bool isNonEphemeral() const { return Flags.isNonEphemeral(); }
28592868

2869+
/// Whether the parameter is 'isolated'.
2870+
bool isIsolated() const { return Flags.isIsolated(); }
2871+
28602872
/// Whether the parameter is marked '@noDerivative'.
28612873
bool isNoDerivative() const { return Flags.isNoDerivative(); }
28622874

@@ -6227,7 +6239,7 @@ inline TupleTypeElt TupleTypeElt::getWithType(Type T) const {
62276239
/// Create one from what's present in the parameter decl and type
62286240
inline ParameterTypeFlags ParameterTypeFlags::fromParameterType(
62296241
Type paramTy, bool isVariadic, bool isAutoClosure, bool isNonEphemeral,
6230-
ValueOwnership ownership, bool isNoDerivative) {
6242+
ValueOwnership ownership, bool isolated, bool isNoDerivative) {
62316243
// FIXME(Remove InOut): The last caller that needs this is argument
62326244
// decomposition. Start by enabling the assertion there and fixing up those
62336245
// callers, then remove this, then remove
@@ -6237,7 +6249,8 @@ inline ParameterTypeFlags ParameterTypeFlags::fromParameterType(
62376249
ownership == ValueOwnership::InOut);
62386250
ownership = ValueOwnership::InOut;
62396251
}
6240-
return {isVariadic, isAutoClosure, isNonEphemeral, ownership, isNoDerivative};
6252+
return {isVariadic, isAutoClosure, isNonEphemeral, ownership, isolated,
6253+
isNoDerivative};
62416254
}
62426255

62436256
inline const Type *BoundGenericType::getTrailingObjectsPointer() const {

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ NODE(ImplErrorResult)
133133
NODE(InOut)
134134
NODE(InfixOperator)
135135
CONTEXT_NODE(Initializer)
136+
NODE(Isolated)
136137
NODE(KeyPathGetterThunkHelper)
137138
NODE(KeyPathSetterThunkHelper)
138139
NODE(KeyPathEqualsThunkHelper)

include/swift/Demangling/TypeDecoder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class FunctionParam {
7373
Flags = Flags.withValueOwnership(ownership);
7474
}
7575
void setNoDerivative() { Flags = Flags.withNoDerivative(true); }
76+
void setIsolated() { Flags = Flags.withIsolated(true); }
7677
void setFlags(ParameterFlags flags) { Flags = flags; };
7778

7879
FunctionParam withLabel(StringRef label) const {
@@ -1415,6 +1416,12 @@ class TypeDecoder {
14151416
hasParamFlags = true;
14161417
break;
14171418

1419+
case NodeKind::Isolated:
1420+
param.setIsolated();
1421+
node = node->getFirstChild();
1422+
hasParamFlags = true;
1423+
break;
1424+
14181425
case NodeKind::AutoClosureType:
14191426
case NodeKind::EscapingAutoClosureType:
14201427
param.setAutoClosure();

0 commit comments

Comments
 (0)