Site icon image技術メモ

[SE-0449]Allow nonisolated to prevent global actor interference

参照


提案概要

  • 型に対して nonisolated を記述できるようになる

なぜ必要か

  • ある型が、GlobalActor隔離されたProtocolに準拠する際に、Actor隔離したくないケースがある
    • 上記ケースにおいては、従来の場合、Protocol由来のMethodをextensionに記述した上で nonisolated を関数に付与する必要があり、冗長
    • 更に、上記対応を行なっても、型自体をActor隔離から除外することはできていない問題がある
@MainActor
protocol P {
  var x: Int { get }
}

struct S {}

extension S: P {
  nonisolated var x: Int {
    get { 1 }
  }
  nonisolated func test() {
    print(x)
  }
}

  • また、あるProtocolが複数のProtocolに準拠しており、準拠しているProtocolが別々のActorに隔離されている場合、どのActorにも隔離されないが、この仕様自体がわかりにくい
    • 明示的にnonisolatedを付けることができるようになれば、より可読性が高まる
final class FakeExecutor: SerialExecutor {
  static let shared: FakeExecutor = .init()
  
  func enqueue(_ job: consuming ExecutorJob) {
    fatalError()
  }
}

@globalActor
public actor FakeGlobalActor: Sendable {
  public static var shared = FakeGlobalActor()
  
  private init() {}
  public nonisolated var unownedExecutor: UnownedSerialExecutor {
    FakeExecutor.shared.asUnownedSerialExecutor()
  }
}

@MainActor
protocol GloballyIsolated {}

@FakeGlobalActor
protocol RemoveGlobalActor {}

protocol RefinedProtocol: GloballyIsolated, RemoveGlobalActor {} // 'RefinedProtocol' is non-isolated

どのように使うか

  • 型に対して nonisolated を付与する
nonisolated struct S: GloballyIsolated, NonIsolatedProto {} // 'S' won't inherit isolation from 'GloballyIsolated' protocol

いつ使うか

  • 型をActor隔離したくない場合

その他備考

  • -enable-experimental-feature GlobalActorInferenceCutoff
  • この提案によって、extension句にもnonisolatedを付与できるようになる
    nonisolated extension Hoge: GloballyIsolated {
      // 略
    }