@Joe_Groff (Joe Groff) posted a new topic, subject "SE-0316 (second review): Global Actors". It read:

   Hi everyone. The second review of SE-0316: Global Actors begins now and runs through June 28th, 2021. The previous review ended on June 7th. Relative to the previous review, the following changes have been made:
    
      * Added the `GlobalActor` protocol, to which all global actors implictly conform.
      * Remove the requirement that all global and static variables be annotated with a global actor.
      * Added a grammar for closure attributes.
      * Clarified the interaction between the main actor and the main thread. Make the main actor a little less "special" in the initial presentation.
    
    
    
    The core team would like to request feedback on the inference rules for global actors during this review. These did not get much attention in the last review cycle, and with vendors now shipping the proposed feature in beta toolchains, we would like to hear about issues that have arisen from real world experience.
    
    This review is part of the large concurrency feature , which we are reviewing in several parts. While we've tried to make it independent of other concurrency proposals that have not yet been reviewed, it may have some dependencies that we've failed to eliminate. Please do your best to review it on its own merits, while still understanding its relationship to the larger feature. You may also want to raise interactions with previous already-accepted proposals – that might lead to opening up a separate thread of further discussion to keep the review focused.
    
    Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager. If you do email me directly, please put "SE-0316" somewhere in the subject line.
    
    ##  What goes into a review?
    
    The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:
    
      * What is your evaluation of the proposal?
      * Is the problem being addressed significant enough to warrant a change to Swift?
      * Does this proposal fit well with the feel and direction of Swift?
      * If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
      * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    
    
    
    More information about the Swift evolution process is available at:
    
    > https://github.com/apple/swift-evolution/blob/master/process.md 
    
    Thank you for participating in improving Swift!
    
    Joe Groff  
    Review Manager

Then @Zhu_Shengqi (Zhu Shengqi) said

    The definition of global actor somehow reverted back to the one in the first pitch:
    [code] 
        @globalActor
        public struct SomeGlobalActor {
          public static let shared = SomeGlobalActor()
        }
        
    [/code]
    
    I guess this result from the fact that we now introduce `GlobalActor` as formal protocol. But `shared` instance here is a struct instead of an actor.
    
    And from the proposal we now allow associated type `ActorType` be different from the type conforming to the protocol. I still consider the case confusing when we use `@MyGlobalActor` to annotate a global variable while `MyGlobalActor` is just a factory type that provides a shared actor of different type.

Then @jmjauer (Johannes Auer) said

    Nested functions seem to be outside of a global actor if the outer function is part of a global actor. This is somewhat unhandy.

@Zhu_Shengqi (Zhu Shengqi) replied

    Several thoughts after reading the proposal:
    
      * We may need a formal definition of the `nonisolated` modifier. Previously this modifier was only used to annotate properties and methods of an actor type, but since we use this modifier in global actor isolated types, I think we should define its semantics and usage in a formal way.
    
      * From the semantics perspective, the global actor attribute is used to annotate a function/property/type so that it's isolated to that global actor. For more generality (at least from my view), have the authors consider using `@isolated(SomeGlobalActor)` instead of `@SomeGlobalActor`?  
    With this approach we can gain several advantages:
    
        1. `@isolated(SomeGlobalActor)` express the isolation-to-global-actor idea more clearly (although with several more characters).
    
        2. When we use words like `isolated` and `nonisolated` consistently and frequently, it would be easier to educate and learn from the isolation model in the whole community.
    
        3. We can express generics over global actors more elegantly. In the current proposal we have this:
    [code]         @T
            class X<T: GlobalActor> {
              func f() { ... } // constrained to the global actor T
            }
            
    [/code]
    
    The biggest issue I see here is that from the first line of code, we can't decide whether `T` is an attribute name or generics parameter. Its ambiguity can only be resolved when we read the code after that, which means the generics parameter definition goes after its first usage. If we choose the `@isolated(SomeGlobalActor)` approach, we can write like this:
    [code]         @isolated<T: GlobalActor>(T)
            class X<T> {
              func f() { ... } // constrained to the global actor T
            }
            
    [/code]
    
    IMO this reads much smoother and aligns with style of generics property wrappers.
    
      * The author should explain in more detail the related behaviors about the implicit conversion from global-actor-qualified functions to `async` functions. It says
    
    > the `async` function will first "hop" to the global actor before executing its body
    
    So from this sentence, I guess that the compiler implicitly creates a new `async` function that wraps the original one. But what if we call the converted function on the same global actor? For instance, see the code below:
    [code]     @MainActor
        func foo(_ closure: () async -> Void) async {
          await closure()
        }
        
        let callback: @MainActor () -> Void = ...
        let callbackAsynchly: () async -> Void = callback
        foo(callbackAsynchly)
        
    [/code]
    
    Will there be additional hops when we execute `closure` inside `foo`? Will this behavior decided by the corresponding global actor type? I hope these questions could be answered.

@filip-sakel (Filip Sakel) replied

    I really like the addition of the `GlobalActor` protocol and appreciate the ability to isolate data to `GlobalActor`-constrained generic parameters. It's definitely a +1 from me!
    
    * * *
    
    Also, I wonder what the compiler uses to differentiate global actors. I imagine it's type identity, which would mean that super- and sub-classes are treated as different global actors. Is this correct?
    
    > A witness that is not inside an actor type infers actor isolation from a protocol requirement that is satisfies, so long as the protocol conformance is stated within the same type definition or extension as the witness:
    
    Are default implementations considered witnesses? If not, it seems reasonable that they — like witnesses — inherit the corresponding requirement's isolation.
    
    > The accessors of a variable or subscript declared with a global actor attribute become isolated to the given global actor. (This includes observing accessors on a stored variable.)
    
    Could this rule be relaxed in the future, allowing multiple accessors to be isolated to different global actors? This would be useful for UI frameworks that both get and set state through a _single_ property declaration, and that require state to remain constant during updates. For example, SwiftUI's `@State` could declare `wrappedValue` as:
    [code] 
        var wrappedValue: Value {
            @MainActor get
            @PostUpdateActor get
            @PostUpdateActor set
        }
        
    [/code]
    
    Then, event handlers, such as `onTapGesture`, would provide an `@PostUpdateActor`-isolated closure:
    [code] 
        func onTapGesture(
            count: Int = 1,
            perform action: @PostUpdateActor @escaping () -> Void
        ) -> some View
        
    [/code]
    
    * * *
    
    Nits:
    
      1. In my opinion, `callbackAsyncly` and `callbackAsynchronously` read better than `callbackAsynchly`.
      2. The AppKit sample code uses `UIViewController` instead of `NSViewController`.

To which @Joe_Groff (Joe Groff) replied

    Zhu_Shengqi:
    
    > The definition of global actor somehow reverted back to the one in the first pitch:
    [code] 
    >     @globalActor
    >     public struct SomeGlobalActor {
    >       public static let shared = SomeGlobalActor()
    >     }
    >     
    [/code]
    > 
    > I guess this result from the fact that we now introduce `GlobalActor` as formal protocol. But `shared` instance here is a struct instead of an actor.
    > 
    > And from the proposal we now allow associated type `ActorType` be different from the type conforming to the protocol. I still consider the case confusing when we use `@MyGlobalActor` to annotate a global variable while `MyGlobalActor` is just a factory type that provides a shared actor of different type.
    
    Being able to separate the global actor type from the actor implementation allows for multiple global actor instances to share the same implementation, which could be useful for common global actor patterns such as a set of global variables guarded by a mutex.

So @Chris_Lattner3 (Chris Lattner) replied

    Joe_Groff:
    
    > Being able to separate the global actor type from the actor implementation allows for multiple global actor instances to share the same implementation, which could be useful for common global actor patterns such as a set of global variables guarded by a mutex.
    
    I don't understand the writing in the proposal, this is probably just a bug in the writing: Emphasis mine:
    
    " A global actor is a type that has the `@globalActor` attribute and contains a `static` property named `shared` that **provides a shared instance of an actor.** "  
    ...
    [code] 
        @globalActor public struct SomeGlobalActor { 
          public static let shared = SomeGlobalActor() 
        }
        
    [/code]
    
    The global actor type need not itself be an actor type; it is essentially just a marker type that provides access to the actual shared actor instance via `shared` . The shared instance is a globally-unique **actor instance**.
    
    However, "shared" has struct type in the example, not actor type.
    
    -Chris

After which, @Zhu_Shengqi (Zhu Shengqi) added

    I have some question about **Global actor-constrained generic parameters** section. What are the benefits of writing a type that has a global-actor-constrained generic parameter? If the type's instances are allowed to run on different global actors, why not change this type into an actor type? Swift concurrency runtime could do more optimization I suppose.

Then @BigSur ({ @MainActor  in M1.Ultra }(Swift)) said

    From the proposal..
    [code] 
        The global actor type need not itself be an actor type;
        it is essentially just a marker type that provides access to the actual shared actor instance via shared. 
        
    [/code]
    
    Whether `class based globalActor` support **inheritance**?
    [code] 
        @globalActor
        class Base{
            static let shared = Base()
            // shared mutable states...
        }
        //OR
        @globalActor
        class Base{
            actor SomeActor {}
            static let shared = SomeActor()
            // shared mutable states...
        }
        class Sub:Base{...}//propagate @Base globalActor attritube
        
    [/code]
    
    We have `class` and `actor` as separate ref type, but how about `@globalActor class` ...? Is it a class or (global)actor, or a `class as @globalActor` with class-inheritance capability?
    
    In other words, `@globalActor class` is a special type in-between with `class+actor` duality?
    
      * class
      * @globalActor class
      * actor
    
    
    
    * * *
    
    but this should definitely work, right? 
    [code]
        @GA
        class Base{...}
        
        class Sub:Base {...}
        
    [/code]
    
    Both `Sub` and `Base` share the same @GA `globalActor`, and support actor-like inheritance without problem.

@Chris_Lattner3 (Chris Lattner) replied

    Joe_Groff:
    
    >   * What is your evaluation of the proposal?
    >   * Is the problem being addressed significant enough to warrant a change to Swift?
    >   * Does this proposal fit well with the feel and direction of Swift?
    >   * If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
    >   * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    > 
    
    
    I'm +1 on this proposal.
    
    -Chris

To which @Douglas_Gregor (Douglas Gregor) replied

    Zhu_Shengqi:
    
    > The definition of global actor somehow reverted back to the one in the first pitch:
    [code] 
    >     @globalActor
    >     public struct SomeGlobalActor {
    >       public static let shared = SomeGlobalActor()
    >     }
    >     
    [/code]
    > 
    > I guess this result from the fact that we now introduce `GlobalActor` as formal protocol. But `shared` instance here is a struct instead of an actor.
    
    I'll fix the proposal. It should look like this:
    [code] 
        @globalActor
        public struct SomeGlobalActor {
          public actor MyActor { }
        
          public static let shared = MyActor()
        }
        
    [/code]
    
    Zhu_Shengqi:
    
    > I still consider the case confusing when we use `@MyGlobalActor` to annotate a global variable while `MyGlobalActor` is just a factory type that provides a shared actor of different type.
    
    `MyGlobalActor` is providing the type identity for the global actor. There's an underlying actor instance that handles the coordination, which is accessed via `shared`.
    
    Zhu_Shengqi:
    
    > We may need a formal definition of the `nonisolated` modifier. Previously this modifier was only used to annotate properties and methods of an actor type, but since we use this modifier in global actor isolated types, I think we should define its semantics and usage in a formal way.
    
    Hmm, I wonder what this would look like. `nonisolated` disables the implicit propagation of actor isolation, whether from an actor type or a global actor.
    
    Zhu_Shengqi:
    
    > From the semantics perspective, the global actor attribute is used to annotate a function/property/type so that it's isolated to that global actor. For more generality (at least from my view), have the authors consider using `@isolated(SomeGlobalActor)` instead of `@SomeGlobalActor` ?
    
    This would be different from the other kinds of custom attributes (property wrappers, result builders), so I think we'd need to convince ourselves that something like `@MainActor` is insufficiently clear to both deviate from other custom attributes and make its use significantly longer.
    
    Zhu_Shengqi:
    
    > We can express generics over global actors more elegantly. In the current proposal we have this:
    [code] 
    >     @T
    >     class X<T: GlobalActor> {
    >       func f() { ... } // constrained to the global actor T
    >     }
    >     
    [/code]
    > 
    > The biggest issue I see here is that from the first line of code, we can't decide whether `T` is an attribute name or generics parameter. Its ambiguity can only be resolved when we read the code after that, which means the generics parameter definition goes after its first usage. If we choose the `@isolated(SomeGlobalActor)` approach, we can write like this:
    [code] 
    >     @isolated<T: GlobalActor>(T)
    >     class X<T> {
    >       func f() { ... } // constrained to the global actor T
    >     }
    >     
    [/code]
    > 
    > IMO this reads much smoother and aligns with style of generics property wrappers.
    
    To me it looks like it's parameterizing the attribute, not the whole declaration. Are the generic requirements of the `@isolated` required to exactly match those of `T`? If there is a `where` clause, where does it go?
    
    This issue of referencing generic parameters before they are declared (but in the same declaration) isn't totally new. We do it with the underscored `@_specialize` attribute:
    [code] 
        @_specialize(exported: true, where T==UInt)
        func increment<T: BinaryInteger>(_ t: T) -> T {
            let incremented = t + 1
            return incremented
        }
        
    [/code]
    
    Let's say I had to put both a global actor and an `@_specialize` on a declaration. Would I have to declare `T` three times now, and all consistently? I don't think this syntax scales, and I don't think it's clearer.
    
    Zhu_Shengqi:
    
    > The author should explain in more detail the related behaviors about the implicit conversion from global-actor-qualified functions to `async` functions. It says
    >
    >> the `async` function will first "hop" to the global actor before executing its body
    > 
    > So from this sentence, I guess that the compiler implicitly creates a new `async` function that wraps the original one.
    
    Yes, it's effectively this:
    [code] 
        let callbackAsynchly: (Int) async -> Void = {
          await callback() // `await` is required because callback is `@MainActor`
        }
        
    [/code]
    
    Zhu_Shengqi:
    
    > Will there be additional hops when we execute `closure` inside `foo` ? Will this behavior decided by the corresponding global actor type?
    
    An actor "hop" is a no-op if you're already running on that actor.
    
    filip-sakel:
    
    > Also, I wonder what the compiler uses to differentiate global actors. I imagine it's type identity, which would mean that super- and sub-classes are treated as different global actors. Is this correct?
    
    Yes, that's correct. Global-actor-ness isn't inherited, either, so you could have a `@globalActor` superclass and then use one of its subclasses as an attribute.
    
    filip-sakel:
    
    > > A witness that is not inside an actor type infers actor isolation from a protocol requirement that is satisfies, so long as the protocol conformance is stated within the same type definition or extension as the witness:
    > 
    > Are default implementations considered witnesses? If not, it seems reasonable that they — like witnesses — inherit the corresponding requirement's isolation.
    
    Default implementations aren't really a construct in the language. They're declarations in a protocol that can be used to witness a requirement if there is no better option. So. they don't infer isolation.
    
    filip-sakel:
    
    > > The accessors of a variable or subscript declared with a global actor attribute become isolated to the given global actor. (This includes observing accessors on a stored variable.)
    > 
    > Could this rule be relaxed in the future, allowing multiple accessors to be isolated to different global actors? This would be useful for UI frameworks that both get and set state through a _single_ property declaration, and that require state to remain constant during updates. For example, SwiftUI's `@State` could declare `wrappedValue` as:
    [code] 
    >     var wrappedValue: Value {
    >         @MainActor get
    >         @PostUpdateActor get
    >         @PostUpdateActor set
    >     }
    >     
    [/code]
    
    Hmm. I don't think it's technically impossible to implement this, but it's a lot of extensions: we don't permit overloading of accessors today, nor do we permit overloading based on the global actor.
    
    Chris_Lattner3:
    
    > I don't understand the writing in the proposal, this is probably just a bug in the writing: Emphasis mine:
    > 
    > " A global actor is a type that has the `@globalActor` attribute and contains a `static` property named `shared` that **provides a shared instance of an actor.** "
    
    It's a bug in the example. I've fixed it in the proposal (see above).
    
    Zhu_Shengqi:
    
    > I have some question about **Global actor-constrained generic parameters** section. What are the benefits of writing a type that has a global-actor-constrained generic parameter? If the type's instances are allowed to run on different global actors, why not change this type into an actor type? Swift concurrency runtime could do more optimization I suppose.
    
    @anandabits provided some rationale here. Global actors let you pull in declarations from all of your program to synchronize on a single actor, which you can't do with actor types.
    
    Doug

So @Zhu_Shengqi (Zhu Shengqi) replied

    Douglas_Gregor:
    
    > This issue of referencing generic parameters before they are declared (but in the same declaration) isn't totally new. We do it with the underscored `@_specialize` attribute:
    [code] 
    >     @_specialize(exported: true, where T==UInt)
    >     func increment<T: BinaryInteger>(_ t: T) -> T {
    >         let incremented = t + 1
    >         return incremented
    >     }
    >     
    [/code]
    > 
    > Let's say I had to put both a global actor and an `@_specialize` on a declaration. Would I have to declare `T` three times now, and all consistently? I don't think this syntax scales, and I don't think it's clearer.
    
    The `@_specialize` syntax is part of implementation detail instead of public language feature, so it's less convincing as a precedent for the new syntax introduced in this proposal.
    
    Douglas_Gregor:
    
    > @anandabits provided some rationale here . Global actors let you pull in declarations from all of your program to synchronize on a single actor, which you can't do with actor types.
    
    The rationale provided is "I have a library that encodes concurrency context in the type system and limits some functionality to objects (each managing a piece of state) that share the same context. ". I suggest we can provide more use case around the generic parameter of global actor types, so that we could discuss around these use case instead of pure functionality. If we concludes after discussion that we don't need this generics functionality, I think we can use this syntax:
    [code] 
        @isolated(MyActor.shared_2)
        class SomeClass { ... }
        
        @isolated(MyActor.shared_2)
        class AnotherClass { ... }
        
    [/code]
    
    With this approach we no longer need the protocol definition for global actors (even the ad-hoc one in previous rounds), and have the flexibility to define multiple global actor instances in a single namespace. I also admit `@MainActor` is easier to use than `@isolated(MainActor.shared)`, but we can make an exception for the main actor in this case.

So @anandabits (Matthew Johnson) replied

    Zhu_Shengqi:
    
    > have the flexibility to define multiple global actor instances in a single namespace
    
    You can have this flexibility with the current design:
    [code] 
        enum MyNamespace {
            @globalActor enum GlobalActor1 { static let shared = SomeActor() }
            @globalActor enum GlobalActor2 { static let shared = SomeOtherActor() }
        }
        
    [/code]

@Zhu_Shengqi (Zhu Shengqi) replied

    With the current design we need to add an additional layer (`GlobalActor1` and `GlobalActor2`) around those underlying actor instances. Which seems some unnecessary boilerplate to me. With the version I suggested we could just write:
    [code] 
        enum MyNamespace {
            static let shared_1 = SomeActor()
            static let shared_2 = SomeOtherActor()
        }
        
    [/code]

To which @anandabits (Matthew Johnson) replied

    I disagree that the proposed design is unnecessary boilerplate. It is an approach that is consistent with the rest of Swift whereas your suggestion looks like ad-hoc magic.
    
    Further, global actor declarations will be extremely rare relative to global actor usage. Your approach increases boilerplate at the usage site which will result in significantly more total "boilerplate" than the proposed design.
    
    Unrelated, I noticed that the text in the proposal just mentions a static property `shared` while the `GlobalActor` protocol goes further and specifies: "The value of this property must always evaluate to the same actor instance."
    
    Normal Swift protocols cannot express a constant requirement, but given that this is a magic ad-hoc protocol in the compiler I think it would be a good idea to require `shared` to be a constant. Are there any valid use cases where it would not be @Douglas_Gregor?

Then @Zhu_Shengqi (Zhu Shengqi) said

    anandabits:
    
    > I disagree that the proposed design is unnecessary boilerplate. It is an approach that is consistent with the rest of Swift whereas your suggestion looks like ad-hoc magic.
    
    I'm NOT saying the proposed design is unnecessary boilerplate. I'm just comparing the code snippet you provided with mine, and in THIS specific case I regard declaring an additional layer to enclose global actor instances seems unnecessary boilerplate (at least it contains more code). I'd be happy if we could solve this redundancy if possible.
    
    And by saying "ad-hoc magic" can you be more specific on this?
    
    anandabits:
    
    > Further, global actor declarations will be extremely rare relative to global actor usage. Your approach increases boilerplate at the usage site which will result in significantly more total "boilerplate" than the proposed design.
    
    I agree that with my version there is more text in the use site. It's somewhat longer function names versus deeper nested namespaces. I hope we could come up with a solution with moth succinct attribute strings and shallow declarations.

@Zhu_Shengqi (Zhu Shengqi) replied

    anandabits:
    
    > It is an approach that is consistent with the rest of Swift whereas your suggestion looks like ad-hoc magic.
    
    Just to point out that this is the review thread of a Swift proposal. If you assert that "It is an approach that is consistent with the rest of Swift" while saying "your suggestion looks like ad-hoc magic", what is the point of the review and discussion here? I raise concerns and give some suggestions in this thread, and those suggestions don't need to be the polished alternatives I think. We could discuss pros and cons of each approach and make the language better through this process.

To which @anandabits (Matthew Johnson) replied

    Zhu_Shengqi:
    
    > We could discuss pros and cons of each approach and make the language better through this process.
    
    That's what I am attempting to do. To elaborate on the previous points, Swift already uses `@propertyWrapper` and `@resultBuilder` for ad-hoc protocols that create user-defined attributes. As far as I know, there is no precedent for an attribute argument referencing an arbitrary declaration that takes a very specific shape (such as identifying a global actor).

To which @Douglas_Gregor (Douglas Gregor) replied

    Zhu_Shengqi:
    
    > I think we can use this syntax:
    [code] 
    >     @isolated(MyActor.shared_2)
    >     class SomeClass { ... }
    >     
    >     @isolated(MyActor.shared_2)
    >     class AnotherClass { ... }
    >     
    [/code]
    > 
    > With this approach we no longer need the protocol definition for global actors (even the ad-hoc one in previous rounds), and have the flexibility to define multiple global actor instances in a single namespace.
    
    Aside from breaking the proposal's consistency with property wrappers and result builders, this means we need to establish a notion of identity based on _expressions_ like `MyActor.shared_2`. If I were to write
    [code] 
        @isolated(MyModule.MyActor.shared_2)
        class AThirdClass { ... }
        
    [/code]
    
    would that be the same "global actor" as `SomeClass` and `AnotherClass`? Keep in mind that we also have to do this evaluation at runtime, e.g., for dynamic casting:
    [code] 
        typealias Fn = @isolated(MyModule.MyActor.shared_2) (Int) -> Int
        if let fn = anyValue as? Fn { ... }
        
    [/code]
    
    so we need to encode the entire expression in runtime metadata.
    
    The great thing about using types for identity is that their notion of identity is well-defined and well-understood throughout the entire compiler and runtime. Your approaches has to create a new notion of identity.
    
    anandabits:
    
    > Normal Swift protocols cannot express a constant requirement, but given that this is a magic ad-hoc protocol in the compiler I think it would be a good idea to require `shared` to be a constant. Are there any valid use cases where it would not be @Douglas_Gregor?
    
    I don't think this is a good idea. It's reasonable for someone to want to create a global actor that uses a computed property (that produces a consistent value) in lieu of a `let`.
    
    Doug

To which @anandabits (Matthew Johnson) replied

    Douglas_Gregor:
    
    > It's reasonable for someone to want to create a global actor that uses a computed property (that produces a consistent value) in lieu of a `let`
    
    It seems pretty unlikely to me that there would be a computed property that does something more than a constant initialization could do while still consistently returning the same instance. On the other hand, I can easily imagine people violating the global actor contract unintentionally.

@Douglas_Gregor (Douglas Gregor) replied

    anandabits:
    
    > It seems pretty unlikely to me that there would be a computed property that does something more than a constant initialization could do while still consistently returning the same instance. On the other hand, I can easily imagine people violating the global actor contract unintentionally.
    
    It seems pretty unlike to me that anyone will use anything other than `static let` here in the first place, so when we're talking about adding a special ad-hoc type-checking rule for a rare case that might be useful. Heck, you need it today if you want a generic global actor, because static variables aren't supported in generic types:
    [code] 
        protocol DefaultInitializable {
          init()
        }
        
        @globalActor
        struct GA<ActorType: Actor & DefaultInitializable> {
          static let shared = ActorType() // error: static stored properties not supported in generic types
        }
        
    [/code]
    
    Doug

After which, @Joe_Groff (Joe Groff) added

    Thanks everybody for your help in the review. The core team has decided to accept this proposal with modifications.

So @xwu (Xiaodi Wu) replied

    I'm late to the review, seeing as it's already been accepted (congratulations!). I wonder if @Douglas_Gregor or another author could give a clarification that seems unanswered in the proposal text--
    
    The proposal gives the following example:
    
    > 
    [code]
    >     protocol P {
    >       @MainActor func f()
    >     }
    >     
    >     struct X { }
    >     
    >     extension X: P {
    >       func f() { } // implicitly @MainActor
    >     }
    >     
    [/code]
    
    What happens if I define two global actor-annotated protocols, `P` and `Q` (distinct global actors), and then write `struct X: P, Q`? Which is the implicit global actor then, and is there a warning?
    
    In the same vein, but perhaps more likely to occur in real-world code, the proposal states:
    
    > A struct or class containing a wrapped instance property with a global actor-qualified wrappedValue infers actor isolation from that property wrapper:
    [code] 
    >     @propertyWrapper
    >     struct UIUpdating<Wrapped> {
    >       @MainActor var wrappedValue: Wrapped
    >     }
    >     
    >     struct CounterView { // infers @MainActor from use of @UIUpdating
    >       @UIUpdating var intValue: Int = 0
    >     }
    >     
    [/code]
    
    What if I define a struct with two members, one annotated with `@UIUpdating` and another annotated with a custom property wrapper called `@BackgroundActorUpdating` with a different global actor-qualified wrapped value? What is the inferred global actor for my struct, and is there a warning?


{'source': 'discourse', 'url': 'https://forums.swift.org/t/se-0316-second-review-global-actors/49804', 'title': 'SE-0316 (second review): Global Actors', 'views': 2187, 'has_accepted_answer': False, 'word_count': 4724, 'like_count': 31, 'reply_count': 13, 'participant_count': 9, 'posts': 23, 'tags': '', 'author': '@Joe_Groff (Joe Groff)', 'participants': '@Joe_Groff (Joe Groff), @Zhu_Shengqi (Zhu Shengqi), @jmjauer (Johannes Auer), @filip-sakel (Filip Sakel), @Chris_Lattner3 (Chris Lattner), @BigSur ({ @MainActor \uf8ff in M1.Ultra }(Swift)), @Douglas_Gregor (Douglas Gregor), @anandabits (Matthew Johnson), @xwu (Xiaodi Wu)', 'image_url': [None], 'created_at': '2021-06-21T18:28:56.730Z', 'last_posted_at': '2021-07-01T06:18:23.285Z'}