iosswiftswift-concurrency

Strange error with "Cannot form key path to main actor-isolated property ..." in Swift concurrency


I have this code:

// empty struct for demo purpose.
struct DailyRewardItem {}

@MainActor
protocol Plugin {
  var dailyRewardItems: [DailyRewardItem] { get }
}

enum MagicItemType: CaseIterable {
  case shuffle
  case hammer
  case rocket
  case bomb
  
  @MainActor
  var dailyRewardItem: DailyRewardItem {
    return DailyRewardItem()
  }
}

class MyPlugin: Plugin {
  let dailyRewardItems = MagicItemType.allCases.map(\.dailyRewardItem)
}

I got this warning:

Cannot form key path to main actor-isolated property 'dailyRewardItem'; this is an error in the Swift 6 language mode

Here MyPlugin is implicitly main actor because it extends Plugin. So MyPlugin::dailyRewardItems is also main actor. The keyPath is also in main actor. Not sure why this gives warning.

If I don't use the keyPath, it is working fine without warning.

  let dailyRewardItems = MagicItemType.allCases.map { $0.dailyRewardItem }

I am using Xcode 16 beta 3, Swift 5 with "complete" concurrency checking.


Solution

  • This is a bug, and is fixed in this PR, merged on 2024-07-09, and is now fixed in beta 6.

    From the PR description:

    This allows isolated key-path components to be used in stored property initializers when the stored property itself is isolated to the same global actor.


    Other than using a closure, initialising the property in init also removes the warning in the current version:

    init() {
        dailyRewardItems = MagicItemType.allCases.map(\.dailyRewardItem)
    }