[Pitch] Control default actor isolation inference

I will make this clear in the future directions section, but I think the option should be set by default for new project creation in some cases. I didn't include that in this pitch because I think where this mode should be enabled by default is a separate discussion. It has to be opt-in for existing projects for source compatibility reasons, but we can also make the option more discoverable via compiler diagnostics, e.g. as an alternative when someone gets a concurrency error that suggests adding @MainActor to resolve it.

From my perspective, that's the point. There are many programmers who don't (yet) need to understand this setting at all. Moving toward a model where the default MainActor is always explicitly specified in source code doesn't actually avoid programmers needing to confront the concept of the main actor early on.

I think this is a solvable problem. The compiler and SourceKit can already show inferred actor isolation for any declaration. The compiler also keeps track of the source of actor isolation inference, and it'd be very straightforward to show that too. That's extremely useful independent of this pitch - for example, it can be difficult to determine where @MainActor isolation is inferred from when it comes from a protocol conformance that you didn't conform to directly.

Hah, you're right! We could still make this work with an overload that accepts a string. I'm still against pursuing this direction for the reasons outlined in the section, though.

I think this is feasible, but I don't think this is a better design. It's more difficult to provide actionable diagnostics if someone makes a mistake in specifying the default, e.g. misspelling the typealias name is still perfectly valid Swift code. We'd also need to invent a way to specify nonisolated as the default, either by using a fake type to represent it or by somehow allowing nil to be used on the right side.

I do also worry about this being prone to circularity in the type checker if type checking anything in the default global actor type needs the default actor isolation. static let shared must always be nonisolated, but there's nothing stopping people from writing a more complicated initializer expression that uses other parts of the type that might have the default isolation rules applied (there's no requirement that a global actor type itself be an actor).

2 Likes