i realize that the nominal review period for this is over, so i apologize if this feedback would be better placed elsewhere, but i had a few thoughts/questions on this and some related proposals.
in particular, i'm wondering how the proposal is intended to interact with the recently-approved 'task executor preference' API (SE-0417).
consider the following example:
let op: @Sendable @MainActor () async -> Void = {
MainActor.assertIsolated()
print("main actor")
}
Task(
executorPreference: CustomTaskExecutor.shared,
operation: op
)
based on my reading of the two documents, i would expect the formal isolation of the operation to be resolved to the main actor, and thus would expect the Task to be directly enqued there, effectively bypassing the explicitly-specified TaskExecutor preference. is this interpretation accurate? perhaps it is expected given the current implementation status of things, but this did not appear to be how some of the recent development toolchain snapshots behave.
an additional thought, which admittedly is a bit vague, is in regards to potential 'macro-scale' behavioral changes that this feature may induce in existing code. consider another (somewhat contrived) example where we enqueue a number of tasks of 2 different priorities to be run on the main actor:
func test_priorities() async {
let iterationCount = 100
var done: (() async -> Void)?
for i in 1...iterationCount {
let pri: TaskPriority = (i > iterationCount / 2) ? .high : .low
// aside: an explicit type annotation is needed for some reason.
// @MainActor isolation appears to be dropped without it.
let op: @Sendable @MainActor () async -> Void = {
let qos = qos_class_self()
print("running task: \(i), pri: \(pri), qos: \(qos)")
}
let t = Task(
priority: pri,
operation: op
)
done = { await t.value }
}
await done?()
}
today, due to the initial 'hop' to the generic executor, this form of code will often effectively behave somewhat like a DispatchWorkloop. that is, the Tasks will (often) be run in decreasing priority order. with the enqueuing logic change proposed here, this will no longer be the case, and in this example, all the low priority Tasks will be executed before the high priority ones.
now, i think in this example this is a non-issue (the effective priority of the Tasks is escalated since they run on the main thread), but it at least raises the question of whether this change will potentially lead to priority inversions that did not used to exist, or more generally will have observable and undesirable changes on existing code.
overall this seems like a good addition to the language, and personally i think making initial execution order match Task initialization order where that is possible and reasonable would be a huge win, but do wonder about potential impacts to existing code.