@@ -47,6 +47,78 @@ enum class SILFunctionTypeRepresentation : uint8_t;
4747
4848namespace swift {
4949
50+ // / The formal isolation of a function type.
51+ class FunctionTypeIsolation {
52+ public:
53+ enum class Kind : uint8_t {
54+ // / The function is not isolated.
55+ NonIsolated,
56+
57+ // / The function is isolated to a global actor.
58+ GlobalActor,
59+
60+ // / The function has an isolated parameter; which one is indicated in
61+ // / the parameter list.
62+ Parameter,
63+
64+ // / The function is dynamically isolated.
65+ Dynamic,
66+ };
67+
68+ static constexpr size_t NumBits = 3 ; // future-proof this slightly
69+ static constexpr size_t Mask = (1 << NumBits) - 1 ;
70+
71+ private:
72+ llvm::PointerIntPair<Type, NumBits, Kind> value;
73+
74+ FunctionTypeIsolation (Kind kind, Type type = Type()) : value(type, kind) {}
75+
76+ public:
77+ static FunctionTypeIsolation forNonIsolated () {
78+ return { Kind::NonIsolated };
79+ }
80+ static FunctionTypeIsolation forGlobalActor (Type type) {
81+ assert (type && " creating global actor isolation without an actor type" );
82+ return { Kind::GlobalActor, type };
83+ }
84+ static FunctionTypeIsolation forParameter () {
85+ return { Kind::Parameter };
86+ }
87+ static FunctionTypeIsolation forDynamic () {
88+ return { Kind::Dynamic };
89+ }
90+
91+ Kind getKind () const { return value.getInt (); }
92+ bool isNonIsolated () const {
93+ return getKind () == Kind::NonIsolated;
94+ }
95+ bool isGlobalActor () const {
96+ return getKind () == Kind::GlobalActor;
97+ }
98+ Type getGlobalActorType () const {
99+ assert (getKind () == Kind::GlobalActor);
100+ return value.getPointer ();
101+ }
102+ bool isParameter () const {
103+ return getKind () == Kind::Parameter;
104+ }
105+ bool isDynamic () const {
106+ return getKind () == Kind::Dynamic;
107+ }
108+
109+ // The opaque accessors below are just for the benefit of ExtInfoBuilder,
110+ // which finds it convenient to break down the type separately. Normal
111+ // clients should use the accessors above.
112+
113+ Type getOpaqueType () const {
114+ return value.getPointer ();
115+ }
116+
117+ static FunctionTypeIsolation fromOpaqueValues (Kind kind, Type type) {
118+ return FunctionTypeIsolation (kind, type);
119+ }
120+ };
121+
50122// MARK: - ClangTypeInfo
51123// / Wrapper class for storing a clang::Type in an (AST|SIL)ExtInfo.
52124class ClangTypeInfo {
@@ -373,20 +445,24 @@ class ASTExtInfoBuilder {
373445 // If bits are added or removed, then TypeBase::NumAFTExtInfoBits
374446 // and NumMaskBits must be updated, and they must match.
375447 //
376- // |representation|noEscape|concurrent|async|throws|differentiability|
377- // | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 |
448+ // |representation|noEscape|concurrent|async|throws|isolation| differentiability|
449+ // | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 | 11 .. 13 |
378450 //
379451 enum : unsigned {
380452 RepresentationMask = 0xF << 0 ,
381453 NoEscapeMask = 1 << 4 ,
382454 SendableMask = 1 << 5 ,
383455 AsyncMask = 1 << 6 ,
384456 ThrowsMask = 1 << 7 ,
385- DifferentiabilityMaskOffset = 8 ,
457+ IsolationMaskOffset = 8 ,
458+ IsolationMask = 0x7 << IsolationMaskOffset,
459+ DifferentiabilityMaskOffset = 11 ,
386460 DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
387- NumMaskBits = 11
461+ NumMaskBits = 14
388462 };
389463
464+ static_assert (FunctionTypeIsolation::Mask == 0x7 , " update mask manually" );
465+
390466 unsigned bits; // Naturally sized for speed.
391467
392468 ClangTypeInfo clangTypeInfo;
@@ -403,33 +479,39 @@ class ASTExtInfoBuilder {
403479 LifetimeDependenceInfo lifetimeDependenceInfo)
404480 : bits(bits), clangTypeInfo(clangTypeInfo), globalActor(globalActor),
405481 thrownError (thrownError),
406- lifetimeDependenceInfo(lifetimeDependenceInfo) {}
482+ lifetimeDependenceInfo(lifetimeDependenceInfo) {
483+ assert (isThrowing () || !thrownError);
484+ assert (hasGlobalActorFromBits (bits) == !globalActor.isNull ());
485+ }
407486
408487public:
409488 // / An ExtInfoBuilder for a typical Swift function: @convention(swift),
410489 // / @escaping, non-throwing, non-differentiable.
411490 ASTExtInfoBuilder ()
412491 : ASTExtInfoBuilder(Representation::Swift, false , false , Type(),
413492 DifferentiabilityKind::NonDifferentiable, nullptr,
414- Type(), LifetimeDependenceInfo()) {}
493+ FunctionTypeIsolation::forNonIsolated(),
494+ LifetimeDependenceInfo()) {}
415495
416496 // Constructor for polymorphic type.
417497 ASTExtInfoBuilder (Representation rep, bool throws, Type thrownError)
418498 : ASTExtInfoBuilder(rep, false , throws, thrownError,
419499 DifferentiabilityKind::NonDifferentiable, nullptr ,
420- Type (), LifetimeDependenceInfo()) {}
500+ FunctionTypeIsolation::forNonIsolated (),
501+ LifetimeDependenceInfo()) {}
421502
422503 // Constructor with no defaults.
423504 ASTExtInfoBuilder (Representation rep, bool isNoEscape, bool throws,
424505 Type thrownError, DifferentiabilityKind diffKind,
425- const clang::Type *type, Type globalActor ,
506+ const clang::Type *type, FunctionTypeIsolation isolation ,
426507 LifetimeDependenceInfo lifetimeDependenceInfo)
427508 : ASTExtInfoBuilder(
428509 ((unsigned )rep) | (isNoEscape ? NoEscapeMask : 0 ) |
429510 (throws ? ThrowsMask : 0 ) |
430511 (((unsigned )diffKind << DifferentiabilityMaskOffset) &
431- DifferentiabilityMask),
432- ClangTypeInfo(type), globalActor, thrownError,
512+ DifferentiabilityMask) |
513+ (unsigned (isolation.getKind()) << IsolationMaskOffset),
514+ ClangTypeInfo(type), isolation.getOpaqueType(), thrownError,
433515 lifetimeDependenceInfo) {}
434516
435517 void checkInvariants () const ;
@@ -474,6 +556,26 @@ class ASTExtInfoBuilder {
474556 return lifetimeDependenceInfo;
475557 }
476558
559+ FunctionTypeIsolation::Kind getIsolationKind () const {
560+ return getIsolationKindFromBits (bits);
561+ }
562+ static FunctionTypeIsolation::Kind getIsolationKindFromBits (unsigned bits) {
563+ return FunctionTypeIsolation::Kind (
564+ (bits & IsolationMask) >> IsolationMaskOffset);
565+ }
566+ bool isDynamicallyIsolated () const {
567+ return getIsolationKind () == FunctionTypeIsolation::Kind::Dynamic;
568+ }
569+ static bool hasGlobalActorFromBits (unsigned bits) {
570+ return getIsolationKindFromBits (bits)
571+ == FunctionTypeIsolation::Kind::GlobalActor;
572+ }
573+
574+ FunctionTypeIsolation getIsolation () const {
575+ return FunctionTypeIsolation::fromOpaqueValues (getIsolationKind (),
576+ globalActor);
577+ }
578+
477579 constexpr bool hasSelfParam () const {
478580 switch (getSILRepresentation ()) {
479581 case SILFunctionTypeRepresentation::Thick:
@@ -529,6 +631,7 @@ class ASTExtInfoBuilder {
529631 }
530632 [[nodiscard]]
531633 ASTExtInfoBuilder withThrows (bool throws, Type thrownError) const {
634+ assert (throws || !thrownError);
532635 return ASTExtInfoBuilder (
533636 throws ? (bits | ThrowsMask) : (bits & ~ThrowsMask), clangTypeInfo,
534637 globalActor, thrownError, lifetimeDependenceInfo);
@@ -566,15 +669,19 @@ class ASTExtInfoBuilder {
566669 }
567670
568671 [[nodiscard]]
569- ASTExtInfoBuilder withGlobalActor (Type globalActor) const {
672+ ASTExtInfoBuilder withLifetimeDependenceInfo (
673+ LifetimeDependenceInfo lifetimeDependenceInfo) const {
570674 return ASTExtInfoBuilder (bits, clangTypeInfo, globalActor, thrownError,
571675 lifetimeDependenceInfo);
572676 }
573677
574- [[nodiscard]] ASTExtInfoBuilder withLifetimeDependenceInfo (
575- LifetimeDependenceInfo lifetimeDependenceInfo) const {
576- return ASTExtInfoBuilder (bits, clangTypeInfo, globalActor, thrownError,
577- lifetimeDependenceInfo);
678+ [[nodiscard]]
679+ ASTExtInfoBuilder withIsolation (FunctionTypeIsolation isolation) const {
680+ return ASTExtInfoBuilder (
681+ (bits & ~IsolationMask)
682+ | (unsigned (isolation.getKind ()) << IsolationMaskOffset),
683+ clangTypeInfo, isolation.getOpaqueType (), thrownError,
684+ lifetimeDependenceInfo);
578685 }
579686
580687 bool isEqualTo (ASTExtInfoBuilder other, bool useClangTypes) const {
@@ -664,6 +771,8 @@ class ASTExtInfo {
664771 return builder.getLifetimeDependenceInfo ();
665772 }
666773
774+ FunctionTypeIsolation getIsolation () const { return builder.getIsolation (); }
775+
667776 // / Helper method for changing the representation.
668777 // /
669778 // / Prefer using \c ASTExtInfoBuilder::withRepresentation for chaining.
@@ -712,9 +821,22 @@ class ASTExtInfo {
712821 return builder.withAsync (async).build ();
713822 }
714823
824+ [[nodiscard]]
825+ ASTExtInfo withIsolation (FunctionTypeIsolation isolation) const {
826+ return builder.withIsolation (isolation).build ();
827+ }
828+
829+ [[nodiscard]]
830+ ASTExtInfo withoutIsolation () const {
831+ return builder.withIsolation (FunctionTypeIsolation::forNonIsolated ())
832+ .build ();
833+ }
834+
715835 [[nodiscard]]
716836 ASTExtInfo withGlobalActor (Type globalActor) const {
717- return builder.withGlobalActor (globalActor).build ();
837+ return builder.withIsolation (
838+ FunctionTypeIsolation::forGlobalActor (globalActor))
839+ .build ();
718840 }
719841
720842 [[nodiscard]] ASTExtInfo withLifetimeDependenceInfo (
0 commit comments