SE-0434: Usability of global-actor-isolated types

Hello, Swift community.

The review of SE-0434: Usability of global-actor-isolated types begins now and runs through April 22nd, 2024.

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. When emailing the review manager directly, please put [SE-0434] at the start of the subject line.

Try it out!

You can try this proposal out using a nightly snapshot. You must add -enable-experimental-feature GlobalActorIsolatedTypesUsability to your build.

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/main/process.md

Thank you,

John McCall
Review Manager

13 Likes

I have one item that I think perhaps belongs in the theme of this proposal, which is defaulting @main to be on the main actor.

This is almost always what you want. For apps that initialize views, and for command lines for the same reason that top-level code is implicitly the main actor.

Every time I have to write

@MainActor
@main
struct Main {
  static func main() {

...I remind myself of an item on my to-do list to pitch simplifying this tower of terror. Getting rid of the @MainActor part at least would be a start.[1]

In the cases (which I'm not sure there are strong reasons for) where not starting on the main actor is desirable, nonisolated could be applied to specific functions to undo the default.


  1. We ought also to free the function from having to have a Java-style noun wrapper, but that's a different proposal. ↩︎

18 Likes

I think this makes sense.

In the long term, I'd love to see both steps tackled that you mention, getting us down to top-level @main func main() { ... }. Maybe, even—aping SwiftUI's #Preview—going a step further to just #Main { ... } with a macro.

Not trying to derail the conversation to go down this side quest, but rather thinking it through out loud to say that even in that world, it would probably be useful to have the existing @main imply @MainActor, so I think this is a good step regardless of how the future unfolds.

5 Likes

A pain point of #Preview is you cannot have nested types like you can when using a PreviewProvider approach.

Took a recent development snapshot for a spin with GlobalActorIsolatedTypesUsability and found that local functions don't seem to infer sendability. In this modified code snippet from the proposal:

func test(globallyIsolated: @escaping @MainActor () -> Void) {
  @MainActor func f() {} ⚠️
  Task {
    await globallyIsolated() //okay
    await f() //⚠️
  }
}

:warning: Concurrently-executed local function 'f()' must be marked as '@Sendable'; this is an error in the Swift 6 language mode

:warning: Capture of 'f()' with non-sendable type '() -> ()' in a @Sendable closure; this is an error in the Swift 6 language mode

Is this the expected behavior? It also doesn't seem to be possible to mark f as @MainActor @Sendable. It emits a different warning:

@MainActor @Sendable func f() {} ⚠️

:warning: Main actor-isolated synchronous local function 'f()' cannot be marked as '@Sendable'; this is an error in the Swift 6 language mode