Skip to content

Commit 4d5f29d

Browse files
authored
Merge pull request #72 from stzn/library-evolution
Library Evolutionの翻訳
2 parents c43f60a + 8d43ba2 commit 4d5f29d

File tree

3 files changed

+196
-2
lines changed

3 files changed

+196
-2
lines changed

Guide.docc/CommonProblems.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ var supportedStyleCount: Int {
8787
}
8888
```
8989

90-
もし、この変数を保護するための同期が、コンパイラからは見えない形で行われている場合`nonisolated(unsafe)` を使って `supportedStyleCount` の隔離確認をすべて無効化できます。
90+
もし、この変数を保護するための同期が、コンパイラからは見えない形で行なわれている場合`nonisolated(unsafe)` を使って `supportedStyleCount` の隔離確認をすべて無効化できます。
9191

9292
```swift
9393
/// `styleLock` を保持している間だけこの値にアクセスしてよい。
@@ -264,7 +264,9 @@ class WindowStyler: Styler {
264264
Swiftには、並行処理を段階的に導入し、まだ並行処理を全く使用していないコードと相互運用するための多くのメカニズムがあります。
265265
これらのツールは、自分が所有していないコードはもちろん、所有しているが簡単に変更できないコードに対しても役立ちます。
266266

267-
プロトコルの準拠に `@preconcurrency` のアノテーションをつけると、隔離不一致に関するエラーを抑制できます。
267+
プロトコルの準拠に[`@preconcurrency`][Preconcurrency]のアノテーションをつけると、隔離不一致に関するエラーを抑制できます。
268+
269+
[Preconcurrency]: libraryevolution#preconcurrencyアノテーション
268270

269271
```swift
270272
@MainActor

Guide.docc/LibraryEvolution.md

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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+
```

Guide.docc/MigrationGuide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Swift 6言語モードの導入は、ターゲットごとに完全に制御で
7676
- <doc:CommonProblems>
7777
- <doc:IncrementalAdoption>
7878
- <doc:SourceCompatibility>
79+
- <doc:LibraryEvolution>
7980

8081
### Swift Concurrencyの詳細
8182

0 commit comments

Comments
 (0)