|
| 1 | +# Library Evolution |
| 2 | + |
| 3 | +ソース互換性およびABI互換性を維持しつつ、ライブラリAPIに並行性の注釈をつけましょう。 |
| 4 | + |
| 5 | +|原文|[https://github.com/apple/swift-migration-guide/blob/main/Guide.docc/LibraryEvolution.md](https://github.com/apple/swift-migration-guide/blob/main/Guide.docc/LibraryEvolution.md)| |
| 6 | +|---|---| |
| 7 | +|更新日|2025/2/1(翻訳を最後に更新した日付)| |
| 8 | +|ここまで反映|[https://github.com/apple/swift-migration-guide/commit/38a0e88a23ee9555fc69861328218001e303aac5](https://github.com/apple/swift-migration-guide/commit/38a0e88a23ee9555fc69861328218001e303aac5)| |
| 9 | + |
| 10 | + |
| 11 | +`@MainActor`や`@Sendable`などの並行性のアノテーションは、ソースやABI互換性に影響を与える可能性があります。ライブラリの作成者は、既存のAPIに注釈をつける際に、これらの影響に注意する必要があります。 |
| 12 | + |
| 13 | +## preconcurrencyアノテーション |
| 14 | + |
| 15 | +`@preconcurrency`属性をライブラリAPIへ直接使用すると、クライアントのソースやABI互換性を損なうことなく、コンパイル時にチェックされる新しい並行性要件を段階的に導入できます。 |
| 16 | + |
| 17 | +```swift |
| 18 | +@preconcurrency @MainActor |
| 19 | +struct S { ... } |
| 20 | + |
| 21 | +@preconcurrency |
| 22 | +public func performConcurrently( |
| 23 | + completion: @escaping @Sendable () -> Void |
| 24 | +) { ... } |
| 25 | +``` |
| 26 | + |
| 27 | +新しいエラーを抑制するために、クライアント側で`@preconcurrency import`を使用する必要はありません。クライアントが、最小限の並行性の確認(minimal)でビルドされている場合、`@preconcurrency`の付いたAPIから発生するエラーは抑制されます。完全な並行性の確認、またはSwift 6言語モードでビルドされている場合、エラーは警告になります。 |
| 28 | + |
| 29 | +ABI互換性のために、`@preconcurrency`をつけると並行性のアノテーションがない状態でシンボル名をマングリングします。しかし、あるAPIをいくつかの並行性のアノテーションをつけて導入し、あとで追加の並行性のアノテーションを含むように更新した場合は、`@preconcurrency`をつけるだけだと、マングル化された名前を維持できません。並行性のアノテーションのマングリングをより正確に制御する必要がある場合は、`@_silgen_name`を使用できます。 |
| 30 | + |
| 31 | +C、C++、およびObjective-CからインポートされたすべてのAPIは、自動的に`@preconcurrency`がついていると見なされることに注意してください。`__attribute__((__swift_attr__("<attribute name>")))`を使用することで、ソースまたはABI互換性を損なうことなく、いつでも並行性の属性をそれらのAPIへ適用できます。 |
| 32 | + |
| 33 | +## Sendable |
| 34 | + |
| 35 | +### 具象型の準拠 |
| 36 | + |
| 37 | +具象型に対する`Sendable`への準拠の追加(条件付き準拠を含む)は、実際のところは、通常はソース互換性のある変更です。 |
| 38 | + |
| 39 | +**ソース互換性とABI互換性のある変更**: |
| 40 | + |
| 41 | +```diff |
| 42 | +- public struct S { ... } |
| 43 | ++ public struct S: Sendable { ... } |
| 44 | +``` |
| 45 | + |
| 46 | +他の準拠と同様に、具象型がより特殊化(specialization)された要件を満たしている場合は、`Sendable`への準拠を追加すると、オーバーロードの解決が変わることがあります。ただし、`Sendable`への準拠によって、オーバーロードするAPIがソース互換性やプログラムの動作を損なうような方法で型推論を変えてしまう可能性は低いです。 |
| 47 | + |
| 48 | +具象型の`Sendable`への準拠の追加(かつ、その型パラメータの1つではない場合)は、常にABI互換性のある変更です。 |
| 49 | + |
| 50 | +## ジェネリック要件 |
| 51 | + |
| 52 | +`Sendable`への準拠要件をジェネリック型または関数に追加すると、クライアントから渡されるジェネリック引数に制限が課されるため、ソース互換性のない変更となります。 |
| 53 | + |
| 54 | +**ソース互換性とABI互換性のない変更**: |
| 55 | + |
| 56 | +```diff |
| 57 | +-public func generic<T> |
| 58 | ++public func generic<T> where T: Sendable |
| 59 | +``` |
| 60 | + |
| 61 | +**解決方法:** 型または関数の宣言に`@preconcurrency`をつけてエラーを警告に下げ、ABIを維持します: |
| 62 | + |
| 63 | +```swift |
| 64 | +@preconcurrency |
| 65 | +public func generic<T> where T: Sendable { ... } |
| 66 | +``` |
| 67 | + |
| 68 | +### 関数型 |
| 69 | + |
| 70 | +ジェネリック要件と同様に、関数型に`@Sendable`を追加すると、ソース互換性とABI互換性のない変更になります: |
| 71 | + |
| 72 | +**ソース互換性とABI互換性のない変更**: |
| 73 | + |
| 74 | +```diff |
| 75 | +-public func performConcurrently(completion: @escaping () -> Void) |
| 76 | ++public func performConcurrently(completion: @escaping @Sendable () -> Void) |
| 77 | +``` |
| 78 | + |
| 79 | +**解決方法:** 関数の宣言に`@preconcurrency`をつけてエラーを警告に下げ、ABIを維持します: |
| 80 | + |
| 81 | +```swift |
| 82 | +@preconcurrency |
| 83 | +public func performConcurrently(completion: @escaping @Sendable () -> Void) |
| 84 | +``` |
| 85 | + |
| 86 | +## MainActorアノテーション |
| 87 | + |
| 88 | +### プロトコルと型 |
| 89 | + |
| 90 | +プロトコルまたは型宣言に`@MainActor`を追加すると、ソース互換性とABI互換性のない変更になります。 |
| 91 | + |
| 92 | +**ソース互換性とABI互換性のない変更**: |
| 93 | + |
| 94 | +```diff |
| 95 | +-public protocol P |
| 96 | ++@MainActor public protocol P |
| 97 | + |
| 98 | +-public class C |
| 99 | ++@MainActor public class C |
| 100 | +``` |
| 101 | + |
| 102 | +プロトコルと型宣言に`@MainActor`を追加すると、他の並行性のアノテーションよりも影響が大きくなります。これは、`@MainActor`が、プロトコル準拠、サブクラス、`extension`内のメソッドなど、クライアントコード全体で推論されることがあるためです。 |
| 103 | + |
| 104 | +プロトコルまたは型宣言に`@preconcurrency`をつけると、並行性の確認レベルに基づき、アクター隔離違反によるエラーが抑制されます。ただし、`@preconcurrency @MainActor`が、クライアントコード内の他の宣言から推論される可能性がある場合、`@preconcurrency`だけではクライアントのABI互換性を維持できません。例えば、クライアントライブラリの次のAPIについて考えてみましょう。 |
| 105 | + |
| 106 | +```swift |
| 107 | +extension P { |
| 108 | + public func onChange(action: @escaping @Sendable () -> Void) |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +`P`が遡及的(retroactive)に`@preconcurrency @MainActor`でアノテーションされる場合、このアノテーションは、`extension`内のメソッドにおいても推論されます。`extension`内のメソッドが、ABI互換性の制約を持つライブラリの一部である場合、`@preconcurrency`は、並行性関連のすべてのアノテーションを名前マングリングから削除します。この問題は、クライアントライブラリで適切な隔離を設定することで回避できます。例えば、次のようになります。 |
| 113 | + |
| 114 | +```swift |
| 115 | +extension P { |
| 116 | + nonisolated public func onChange(action: @escaping @Sendable () -> Void) |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +宣言のABIを正確に制御するための言語機能が[開発中](https://forums.swift.org/t/pitch-controlling-the-abi-of-a-declaration/75123)です。 |
| 121 | + |
| 122 | +### 関数の宣言と型 |
| 123 | + |
| 124 | +関数の宣言または関数の型に`@MainActor`を追加すると、ソース互換性とABI互換性のない変更になります。 |
| 125 | + |
| 126 | +**ソース互換性とABI互換性のない変更**: |
| 127 | + |
| 128 | +```diff |
| 129 | +-public func runOnMain() |
| 130 | ++@MainActor public func runOnMain() |
| 131 | + |
| 132 | +-public func performConcurrently(completion: @escaping () -> Void) |
| 133 | ++public func performConcurrently(completion: @escaping @MainActor () -> Void) |
| 134 | +``` |
| 135 | + |
| 136 | +**解決方法:** 関数の宣言に`@preconcurrency`をつけてエラーを警告に下げ、ABIを維持します: |
| 137 | + |
| 138 | +```swift |
| 139 | +@preconcurrency @MainActor |
| 140 | +public func runOnMain() { ... } |
| 141 | + |
| 142 | +@preconcurrency |
| 143 | +public func performConcurrently(completion: @escaping @MainActor () -> Void) { ... } |
| 144 | +``` |
| 145 | + |
| 146 | +## `sending`パラメータと戻り値 |
| 147 | + |
| 148 | +戻り値に`sending`を追加すると、クライアントコードの制限が解除され、常にソース互換性とABI互換性のある変更になります。 |
| 149 | + |
| 150 | +**ソース互換性とABI互換性のある変更**: |
| 151 | + |
| 152 | +```diff |
| 153 | +-public func getValue() -> NotSendable |
| 154 | ++public func getValue() -> sending NotSendable |
| 155 | +``` |
| 156 | + |
| 157 | +しかし、パラメータに`sending`を追加すると、呼び出し側でより制限が厳しくなります。 |
| 158 | + |
| 159 | +**ソース互換性とABI互換性のない変更**: |
| 160 | + |
| 161 | +```diff |
| 162 | +-public func takeValue(_: NotSendable) |
| 163 | ++public func takeValue(_: sending NotSendable) |
| 164 | +``` |
| 165 | + |
| 166 | +今のところ、ソース互換性を損なわずにパラメータに新しく`sending`を導入する方法はありません。 |
| 167 | + |
| 168 | +### `@Sendable`を`sending`に置き換える |
| 169 | + |
| 170 | +クロージャのパラメータの既存の`@Sendable`を`sending`に置き換えると、ソース互換性はありますが、ABI互換性のない変更になります。 |
| 171 | + |
| 172 | +**ソース互換性はあるが、ABI互換性のない変更**: |
| 173 | + |
| 174 | +```diff |
| 175 | +-public func takeValue(_: @Sendable @escaping () -> Void) |
| 176 | ++public func takeValue(_: sending @escaping () -> Void) |
| 177 | +``` |
| 178 | + |
| 179 | +**解決方法:** パラメータに`sending`を追加すると名前のマングリングが変更されるため、導入する場合は、`@_silgen_name`を使用してマングル化された名前を維持する必要があります。また、パラメータの位置で`sending`を導入する場合、パラメータの所有権規約(ownership convention)を維持する必要があります。パラメータにすでに所有権修飾子(modifier)を明示的に指定している場合、追加のアノテーションは必要ありません。イニシャライザを除くすべての関数において、所有権規約を維持するために`__shared sending`を使用します: |
| 180 | + |
| 181 | +```swift |
| 182 | +public func takeValue(_: __shared sending NotSendable) |
| 183 | +``` |
| 184 | + |
| 185 | +イニシャライザの場合、`sending`はデフォルトの所有権規約を維持するため、イニシャライザのパラメータに`sending`を導入する場合は、所有権修飾子を指定する必要はありません: |
| 186 | + |
| 187 | +```swift |
| 188 | +public class C { |
| 189 | + public init(ns: sending NotSendable) |
| 190 | +} |
| 191 | +``` |
0 commit comments