A recent thread on Mastodon with @mattie prompted me to put this into a longer form:
Context
With Xcode 26, we have some great tools to profile and detect concurrency issues which may be affecting an app’s performance at runtime. Reproducing “high stress” situations to record instrument telemetry is not always easy (especially when apps require on-device only APIs) and things can get confusing in larger codebases.
There are a number of clues that could be surfaced in the editor at “writing code” time that can help inform one’s decisions before they become bugs to be troubleshooted. In other words, it would be awesome if Xcode/editors eventually bring in awareness of what's going on in concurrency world while writing code.
This was inspired by an older WWDC talk which illustrates the kind of context where additional (visual) hints can be helpful.
The presenters walk the viewer through a few debugging sessions in order to identify performance issues related to blocking the MainActor, parallelisation of tasks and actor contention - very useful! But what if it was easier to avoid them in the first place? Especially now that we have Swift 6.2.
Proactive editor features that could help
- Editor feature: Make it easy to see which actor the compiler will assign to the current function/variable/class/struct in the current scheme.
With "approachable concurrency", there are a number of compiler settings which affect how concurrency works. These are configurable in Build Settings for Xcode projects or the Package.swift. In a larger code base, with various dependencies and targets, it’s very difficult to always be aware of the exact settings that applied.
- Editor feature: on which actor(s) is the current line going to run?
Listing all possibilities from the code base can be critical. I was recently working in app, which made use of @ModelActor for some background SwiftData handling. It was imported via @Environment and used in various views and functions both in their actors, as well as @concurrent. It would be amazing if I could just list all these "callers" so I can decide if my ModelActor choice was appropriate here, before it becomes bottleneck.
- Editor feature: which actor(s) / Tasks are going to await [the highlighted] function?
In Swift, we "await" async functions. Sometimes functions are defined as async, sometimes we "await" because they're on a different actor.
- Editor feature: is an await going to jump actors? (e.g. like the log() from the talk)
- Editor feature: is an await waiting for a
@concurrentfunction? Also, am I awaiting in the current actor or another actor?
In the source editor, we can always see which functions are calling into the current method (based on source code analysis). With Swift concurrency and the fact that the "caller" may be in another target/SPM package and this subject to different concurrency settings, it will be awesome if the editor can also hint at some additional information at the point of "await"
-
Editor feature: is an await jumping to wait for an actor which is already being awaited in the call stack of the current method?
-
Editor feature: is the current code running in a detached
Task? -
Editor feature: Am I awaiting a method of the current actor in a Task that's started also in current actor? (which may hint at having needlessly added a
Task {}to call a method in the same actor, among others)
These are just a few examples but you can imagine the kind of hints we're talking about here. It gets even more interesting when such info is presented for something calling into methods defined in a SPM (which may have different concurrency config than the current project).
PS: I recently blogged this as well, with slightly longer explanation but the gist of it is above.