Skip to content

Commit 0e873e7

Browse files
committed
[Isolated conformances] Change syntax to @<global actor type> P
Instead of using the `isolated P` syntax, switch to specifying the global actor type directly, e.g., class MyClass: @mainactor MyProto { ... } No functionality change at this point
1 parent 87135c3 commit 0e873e7

29 files changed

+365
-78
lines changed

include/swift/AST/ConformanceAttributes.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
namespace swift {
1919

20+
class TypeExpr;
21+
2022
/// Describes all of the attributes that can occur on a conformance.
2123
struct ConformanceAttributes {
2224
/// The location of the "unchecked" attribute, if present.
@@ -28,9 +30,15 @@ struct ConformanceAttributes {
2830
/// The location of the "unsafe" attribute if present.
2931
SourceLoc unsafeLoc;
3032

31-
/// The location of the "@isolated" attribute if present.
32-
SourceLoc isolatedLoc;
33-
33+
/// The location of the "nonisolated" modifier, if present.
34+
SourceLoc nonisolatedLoc;
35+
36+
/// The location of the '@' prior to the global actor type.
37+
SourceLoc globalActorAtLoc;
38+
39+
/// The global actor type to which this conformance is isolated.
40+
TypeExpr *globalActorType = nullptr;
41+
3442
/// Merge other conformance attributes into this set.
3543
ConformanceAttributes &
3644
operator |=(const ConformanceAttributes &other) {
@@ -40,8 +48,12 @@ struct ConformanceAttributes {
4048
preconcurrencyLoc = other.preconcurrencyLoc;
4149
if (other.unsafeLoc.isValid())
4250
unsafeLoc = other.unsafeLoc;
43-
if (other.isolatedLoc.isValid())
44-
isolatedLoc = other.isolatedLoc;
51+
if (other.nonisolatedLoc.isValid())
52+
nonisolatedLoc = other.nonisolatedLoc;
53+
if (other.globalActorType && !globalActorType) {
54+
globalActorAtLoc = other.globalActorAtLoc;
55+
globalActorType = other.globalActorType;
56+
}
4557
return *this;
4658
}
4759
};

include/swift/AST/Decl.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,16 +1806,20 @@ struct InheritedEntry : public TypeLoc {
18061806
/// This is true in cases like ~Copyable but not (P & ~Copyable).
18071807
bool IsSuppressed : 1;
18081808

1809+
/// The global actor isolation provided (for a conformance).
1810+
TypeExpr *globalActorIsolationType = nullptr;
1811+
18091812
public:
18101813
InheritedEntry(const TypeLoc &typeLoc);
18111814

18121815
InheritedEntry(const TypeLoc &typeLoc, ProtocolConformanceOptions options,
18131816
bool isSuppressed = false)
18141817
: TypeLoc(typeLoc), RawOptions(options.toRaw()),
1815-
IsSuppressed(isSuppressed) {}
1818+
IsSuppressed(isSuppressed),
1819+
globalActorIsolationType(options.getGlobalActorIsolationType()) {}
18161820

18171821
ProtocolConformanceOptions getOptions() const {
1818-
return ProtocolConformanceOptions(RawOptions);
1822+
return ProtocolConformanceOptions(RawOptions, globalActorIsolationType);
18191823
}
18201824

18211825
bool isUnchecked() const {
@@ -1827,8 +1831,12 @@ struct InheritedEntry : public TypeLoc {
18271831
bool isPreconcurrency() const {
18281832
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
18291833
}
1830-
bool isIsolated() const {
1831-
return getOptions().contains(ProtocolConformanceFlags::Isolated);
1834+
bool isNonisolated() const {
1835+
return getOptions().contains(ProtocolConformanceFlags::Nonisolated);
1836+
}
1837+
1838+
TypeExpr *getGlobalActorIsolationType() const {
1839+
return globalActorIsolationType;
18321840
}
18331841

18341842
ExplicitSafety getExplicitSafety() const {

include/swift/AST/ProtocolConformance.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,9 @@ class NormalProtocolConformance : public RootProtocolConformance,
546546
/// NominalTypeDecl that declared the conformance.
547547
DeclContext *Context;
548548

549+
/// The global actor isolation for this conformance, if there is one.
550+
TypeExpr *globalActorIsolation = nullptr;
551+
549552
NormalProtocolConformance *ImplyingConformance = nullptr;
550553

551554
/// The mapping of individual requirements in the protocol over to
@@ -593,6 +596,7 @@ class NormalProtocolConformance : public RootProtocolConformance,
593596
Bits.NormalProtocolConformance.HasComputedAssociatedConformances = false;
594597
Bits.NormalProtocolConformance.SourceKind =
595598
unsigned(ConformanceEntryKind::Explicit);
599+
globalActorIsolation = options.getGlobalActorIsolationType();
596600
}
597601

598602
/// Get the protocol being conformed to.
@@ -634,7 +638,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
634638
void setInvalid() { Bits.NormalProtocolConformance.IsInvalid = true; }
635639

636640
ProtocolConformanceOptions getOptions() const {
637-
return ProtocolConformanceOptions(Bits.NormalProtocolConformance.Options);
641+
return ProtocolConformanceOptions(Bits.NormalProtocolConformance.Options,
642+
globalActorIsolation);
638643
}
639644

640645
/// Whether this is an "unchecked" conformance.
@@ -669,9 +674,14 @@ class NormalProtocolConformance : public RootProtocolConformance,
669674
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
670675
}
671676

672-
/// Whether this is an isolated conformance.
673-
bool isIsolated() const {
674-
return getOptions().contains(ProtocolConformanceFlags::Isolated);
677+
/// Whether this is a global-actor isolated conformance.
678+
bool isGlobalActorIsolated() const {
679+
return getOptions().contains(
680+
ProtocolConformanceFlags::GlobalActorIsolated);
681+
}
682+
683+
TypeExpr *getGlobalActorIsolation() const {
684+
return globalActorIsolation;
675685
}
676686

677687
/// Retrieve the location of `@preconcurrency`, if there is one and it is

include/swift/AST/ProtocolConformanceOptions.h

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
namespace swift {
2222

23+
class TypeExpr;
24+
2325
/// Flags that describe extra attributes on protocol conformances.
2426
enum class ProtocolConformanceFlags {
2527
/// @unchecked conformance
@@ -34,16 +36,107 @@ enum class ProtocolConformanceFlags {
3436
/// @retroactive conformance
3537
Retroactive = 0x08,
3638

37-
/// @isolated conformance
38-
Isolated = 0x10,
39+
/// nonisolated, which suppresses and inferred global actor isolation
40+
Nonisolated = 0x10,
41+
42+
/// The conformance is global-actor-isolated; the global actor will be
43+
/// stored separately.
44+
GlobalActorIsolated = 0x20,
3945

4046
// Note: whenever you add a bit here, update
4147
// NumProtocolConformanceOptions below.
4248
};
4349

50+
template<typename TheOptionSet>
51+
struct OptionSetStorageType;
52+
53+
template<typename Flags, typename StorageType>
54+
struct OptionSetStorageType<OptionSet<Flags, StorageType>> {
55+
using Type = StorageType;
56+
};
57+
4458
/// Options that describe extra attributes on protocol conformances.
45-
using ProtocolConformanceOptions =
46-
OptionSet<ProtocolConformanceFlags>;
59+
class ProtocolConformanceOptions {
60+
/// The set of options.
61+
OptionSet<ProtocolConformanceFlags> options;
62+
63+
/// Global actor isolation for this conformance.
64+
TypeExpr *globalActorIsolationType = nullptr;
65+
66+
public:
67+
using StorageType =
68+
OptionSetStorageType<OptionSet<ProtocolConformanceFlags>>::Type;
69+
70+
ProtocolConformanceOptions() { }
71+
72+
ProtocolConformanceOptions(ProtocolConformanceFlags flag)
73+
: ProtocolConformanceOptions(static_cast<StorageType>(flag), nullptr) { }
74+
75+
ProtocolConformanceOptions(StorageType flagBits,
76+
TypeExpr *globalActorIsolationType)
77+
: options(flagBits), globalActorIsolationType(globalActorIsolationType) {
78+
assert(options.contains(ProtocolConformanceFlags::GlobalActorIsolated) ==
79+
(bool)globalActorIsolationType);
80+
}
81+
82+
bool contains(ProtocolConformanceFlags flag) const {
83+
return options.contains(flag);
84+
}
85+
86+
TypeExpr *getGlobalActorIsolationType() const {
87+
return globalActorIsolationType;
88+
}
89+
90+
void setGlobalActorIsolation(TypeExpr *globalActorIsolationType) {
91+
options |= ProtocolConformanceFlags::GlobalActorIsolated;
92+
this->globalActorIsolationType = globalActorIsolationType;
93+
}
94+
95+
/// Retrieve the raw bits for just the flags part of the options. You also
96+
/// need to get the global actor isolation (separately) to reconstitute the
97+
/// options.
98+
StorageType toRaw() const {
99+
return options.toRaw();
100+
}
101+
102+
ProtocolConformanceOptions &operator|=(ProtocolConformanceFlags flag) {
103+
assert(flag != ProtocolConformanceFlags::GlobalActorIsolated &&
104+
"global actor isolation requires a type; use setGlobalActorIsolation");
105+
options |= flag;
106+
return *this;
107+
}
108+
109+
ProtocolConformanceOptions &
110+
operator|=(const ProtocolConformanceOptions &other) {
111+
options |= other.options;
112+
if (other.globalActorIsolationType && !globalActorIsolationType)
113+
globalActorIsolationType = other.globalActorIsolationType;
114+
return *this;
115+
}
116+
117+
ProtocolConformanceOptions &operator-=(ProtocolConformanceFlags flag) {
118+
options -= flag;
119+
if (flag == ProtocolConformanceFlags::GlobalActorIsolated)
120+
globalActorIsolationType = nullptr;
121+
return *this;
122+
}
123+
124+
friend ProtocolConformanceOptions operator|(
125+
const ProtocolConformanceOptions &lhs,
126+
const ProtocolConformanceOptions &rhs) {
127+
ProtocolConformanceOptions result(lhs);
128+
result |= rhs;
129+
return result;
130+
}
131+
132+
friend ProtocolConformanceOptions operator-(
133+
const ProtocolConformanceOptions &lhs,
134+
ProtocolConformanceFlags flag) {
135+
ProtocolConformanceOptions result(lhs);
136+
result -= flag;
137+
return result;
138+
}
139+
};
47140

48141
inline ProtocolConformanceOptions operator|(
49142
ProtocolConformanceFlags flag1,
@@ -52,7 +145,7 @@ inline ProtocolConformanceOptions operator|(
52145
}
53146

54147
enum : unsigned {
55-
NumProtocolConformanceOptions = 5
148+
NumProtocolConformanceOptions = 6
56149
};
57150

58151
} // end namespace swift

include/swift/AST/TypeAttr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ SIMPLE_TYPE_ATTR(_local, Local)
6565
SIMPLE_TYPE_ATTR(_noMetadata, NoMetadata)
6666
TYPE_ATTR(_opaqueReturnTypeOf, OpaqueReturnTypeOf)
6767
TYPE_ATTR(isolated, Isolated)
68+
SIMPLE_TYPE_ATTR(nonisolated, Nonisolated)
6869
SIMPLE_TYPE_ATTR(_addressable, Addressable)
6970
TYPE_ATTR(execution, Execution)
7071

include/swift/AST/TypeCheckRequests.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,25 @@ class ConformanceHasEffectRequest :
475475
bool isCached() const { return true; }
476476
};
477477

478+
class ConformanceIsolationRequest :
479+
public SimpleRequest<ConformanceIsolationRequest,
480+
ActorIsolation(ProtocolConformance *),
481+
RequestFlags::Cached> {
482+
public:
483+
using SimpleRequest::SimpleRequest;
484+
485+
private:
486+
friend SimpleRequest;
487+
488+
// Evaluation.
489+
ActorIsolation
490+
evaluate(Evaluator &evaluator, ProtocolConformance *conformance) const;
491+
492+
public:
493+
// Caching.
494+
bool isCached() const;
495+
};
496+
478497
/// Determine whether the given declaration is 'final'.
479498
class IsFinalRequest :
480499
public SimpleRequest<IsFinalRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ SWIFT_REQUEST(TypeChecker, PolymorphicEffectRequirementsRequest,
407407
SWIFT_REQUEST(TypeChecker, ConformanceHasEffectRequest,
408408
bool(EffectKind, ProtocolConformanceRef),
409409
Cached, NoLocationInfo)
410+
SWIFT_REQUEST(TypeChecker, ConformanceIsolationRequest,
411+
ActorIsolation(ProtocolConformance *), Cached,
412+
NoLocationInfo)
410413
SWIFT_REQUEST(TypeChecker, ResolveTypeRequest,
411414
Type (const TypeResolution *, TypeRepr *, GenericParamList *),
412415
Uncached, NoLocationInfo)

include/swift/AST/TypeRepr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
154154
/// or return an invalid source location if there is no such attribute.
155155
SourceLoc findAttrLoc(TypeAttrKind kind) const;
156156

157+
/// Find a custom attribute within this type, or return NULL if there is
158+
/// no such attribute.
159+
CustomAttr *findCustomAttr() const;
160+
157161
/// Is this type grammatically a type-simple?
158162
inline bool isSimple() const; // bottom of this file
159163

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7915,8 +7915,7 @@ static void getSyntacticInheritanceClause(const ProtocolDecl *proto,
79157915
if (auto superclassTy = genericSig->getSuperclassBound(
79167916
proto->getSelfInterfaceType())) {
79177917
Results.emplace_back(TypeLoc::withoutLoc(superclassTy),
7918-
ProtocolConformanceOptions(),
7919-
/*isPreconcurrency=*/false);
7918+
ProtocolConformanceOptions());
79207919
}
79217920

79227921
InvertibleProtocolSet inverses = InvertibleProtocolSet::allKnown();

lib/AST/ConformanceLookupTable.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
154154
options |= ProtocolConformanceFlags::Preconcurrency;
155155
if (getUnsafeLoc().isValid())
156156
options |= ProtocolConformanceFlags::Unsafe;
157-
if (getIsolatedLoc().isValid())
158-
options |= ProtocolConformanceFlags::Isolated;
157+
if (getNonisolatedLoc().isValid())
158+
options |= ProtocolConformanceFlags::Nonisolated;
159+
if (attributes.globalActorType)
160+
options.setGlobalActorIsolation(attributes.globalActorType);
159161
return options;
160162
}
161163

@@ -211,9 +213,9 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
211213
return attributes.unsafeLoc;
212214
}
213215

214-
/// The location of the @isolated attribute, if any.
215-
SourceLoc getIsolatedLoc() const {
216-
return attributes.isolatedLoc;
216+
/// The location of the isolated modifier, if any.
217+
SourceLoc getNonisolatedLoc() const {
218+
return attributes.nonisolatedLoc;
217219
}
218220

219221
/// For an inherited conformance, retrieve the class declaration

0 commit comments

Comments
 (0)