Skip to content

⚠️ 廃止 (DEPRECATED)

本 RFC は RFC-024:新並行モデル に置き換えられました。

RFC-001 の3層並行アーキテクチャ(L1/L2/L3)、@block/@eager アノテーション、DAG 自動解析などの設計は削除されました。新設計では spawn {} ブロックを唯一の並行プリミティブとして使用し、アノテーションは不要です。

本文書は歴史的参考のためにのみ保持されています。



title: "RFC-001:並作モデルとエラー処理システム"

RFC-001:並作モデルとエラー処理システム

設計ソース

ドキュメント関係
async-whitepaper設計ソース、理論的基盤
language-spec規範目標

概要

YaoXiang の並作モデルを提案する:同期構文でロジックを記述し、ランタイムで自動的に並行実行する。コアメカニズム:3層並行アーキテクチャ + DAG 依存性解析 + Result 型システム。

クイック選択

シナリオ記述方法説明
自動並行アノテーションなし(デフォルト)最大並行性を実現
同期待機@eager依存関係の完了を待機
完全順序@block並行なし、デバッグ用
部分的並行spawn@block スコープ内の並行

動機

現在の主流言語の並行モデルには明確な欠陥がある:

言語並行モデル問題
Rustasync/await + tokio非同期伝染、学習曲線が急
Gogoroutine型安全性なし
PythonasyncioGIL の制限
JavaScriptPromise/asyncコールバックが複雑

コアな矛盾

  1. 透明性 vs 制御性:完全透過だが制御不可 vs 完全制御可能だが不透明
  2. 並行 vs デバッグ可能性:並行プログラムはデバッグが難しい vs デバッグ可能なプログラムは並行にしにくい

提案

1. 並作モデル:3層並行アーキテクチャ

説明:L1/L2/L3 はメンタルモデルであり、ユーザーが異なるシナリオを理解するのに役立つ。実際の実装は1つのメカニズムのみ:DAG 自動解析 + アノテーション制御。

階層メンタルモデル構文実行方式並行度
L1並行禁止@block純粋な逐次実行❌ なし
L2@block 内の並行spawn@block スコープ内の制御可能な並行⚠️ 一部
L3完全並行デフォルト(アノテーションなし)DAG の自動解析✅ 完全

L1: @block 同期モード

yaoxiang
main: () -> Void @block = {
    data1 = fetch_sync("api1")
    data2 = fetch_sync("api2")
    process(data1, data2)    # 厳密な順序、並行なし
}

L2: @block 内の制御可能な並行

yaoxiang
# spawn は @block 関数内部でのみ使用可能
main: () -> Void @block = {
    spawn { data1 = fetch_data("api1") }
    spawn { data2 = fetch_data("api2") }
    # すべての spawn の完了を待機(標準ライブラリが制御)
    process(data1, data2)
}

L3: 完全透過(デフォルト)

yaoxiang
# アノテーションは不要、コンパイラが自動的に DAG を解析
heavy_calc: (n: Int) -> Int = fibonacci(n)

auto_parallel: (n: Int) -> Int = {
    a = heavy_calc(1)    # 自動並行
    b = heavy_calc(2)    # 自動並行
    c = heavy_calc(3)    # 自動並行
    a + b + c            # 値が必要時にすべての結果を待機
}

2. アノテーションの完全な比較

区分デフォルト(アノテーションなし)@eager@blockspawn
実行方式自動 DAG 解析依存関係の同期待機純粋順序@block 内の並行
並行度✅ 完全⚠️ 依存関係の順序に従う❌ なし⚠️ 一部
DAG 構築

選択ガイド

  • 最大並行性 → アノテーションなし(デフォルト)
  • 順序付き副作用が必要 → @eager
  • デバッグ/新手/重要コード → @block
  • @block 内で並行が必要 → spawn
yaoxiang
# デフォルト:最大並行性を実現
calc_all: () -> Int = {
    a = heavy_calc(1)    # 自動並行
    b = heavy_calc(2)    # 自動並行
    a + b
}

# @eager:同期待機
calc_seq: () -> Int @eager = {
    a = heavy_calc(1)    # 同期実行
    b = heavy_calc(2)    # 同期実行
    a + b
}

# @block:純粋順序
calc_simple: () -> Int @block = {
    a = heavy_calc(1)    # 強制的に同期
    b = heavy_calc(2)    # 同期
    a + b
}

# spawn:@block 内の並行
calc_mixed: () -> Int @block = {
    spawn { heavy_calc(1) }
    spawn { heavy_calc(2) }
    heavy_calc(3)        # 同期
}

3. DAG 依存性解析

3.1 コア原則:ボトムアップ実行

ユーザーコード(同期構文):
    a = fetch(url0)
    b = fetch(url1)
    print(a)

コンパイル時解析(ボトムアップ):
    print(a) は a を必要とする → fetch(url0) に依存
    fetch(url1) は誰も必要としていない → 孤立 DAG

ランタイムスケジューリング(叶子から開始):
    fetch(url0) → print(a)    ← 依存チェーン、順序通り
    fetch(url1)                ← 孤立、独立並行

重要な洞察:「トップダウン」で Future を生成するのではなく、「ボトムアップ」で結果から逆算して依存関係を解析する。

3.2 孤立 DAG:独立並行

メインフロー:fetch(url0) → process → print
孤立:  fetch(url1)  ← 誰も結果を必要としていない、独立並行

スケジューラー:メインフローは依存チェーンに従って実行、孤立は別コアで並行

3.3 リソース型と副作用

コアな考え方:リソース操作は型でマークされ、DAG が自動的に依存関係を構築する。同一リソースは自動的に直列化され、異なるリソースは自動的に並行実行される。

リソース型の境界——明確な定義

リソース型はコンパイラの組み込みマーキングされた型である。以下の型はコンパイラによってリソースとして認識される:

リソース型説明コンパイラの動作
FilePathファイルシステムパス同一パス操作は自動的に直列化
HttpUrlHTTP エンドポイント同一 URL 操作は自動的に直列化
DBUrlデータベース接続同一接続操作は自動的に直列化
Console標準出力すべての Console 操作は自動的に直列化

ユーザー定義のリソース型は明示的にマーキングする必要がある:

yaoxiang
Database: Resource              # リソース型として明示的にマーキング
query: (Database, String) -> Result(Row, Error)
# パラメータ Database は Resource で自動的にリソース操作として識別

Resource マーキングのない型は、コンパイラによってリソース依存性が追跡されない。

使用ルール

  • 変数を介してリソースハンドルを渡し、DAG が自動的に順序を管理する
  • リテラルを直接使用して同一リソースを使用するのはユーザーの設計上の問題であり、言語の責任ではない
yaoxiang
# ✅ 正しい:変数による渡し、DAG が自動的に直列化
filename: String = "data.txt"
File.write(filename, x)
File.write(filename, y)    # DAG が直列化

# ⚠️ ユーザーの責任:リテラル
File.write("data.txt", x)
File.write("data.txt", y)  # 並行になる可能性、ユーザーは自己責任

3.4 無限ループ処理

1 つのループ → 直接的に同期実行、ゼロスケジューリングオーバーヘッド
複数のループ → スケジューラーがスライスを切り替え、真の並行性

4. Result 型とエラー処理

yaoxiang
Result: (T: Type, E: Type) -> Type = { ok: (T) -> Self, err: (E) -> Self }

# ? 演算子の透過的な伝播
process: () -> Result(Data, Error) = {
    data = fetch_data()?
    processed = transform(data)?
    save(processed)?
}

5. DAG ノード設計

rust
enum NodeKind {
    Task,      // タスクノード
    Value,     // 値ノード
    Control,   // 制御フローノード
}

struct Node {
    id: NodeId,
    kind: NodeKind,
    inputs: Vec<ValueNodeId>,   // 入力依存
    outputs: Vec<ValueNodeId>,  // 出力値
    span: Span,                 // ソースコードの位置
}
辺の種類記号セマンティクス
DataEdgeデータ依存(値の流動)
ControlEdge制御依存(順序実行)
SpawnEdge並行エントリ(並列可能な開始点)

6. 型システム

Send → スレッド間を安全に転送可能
Sync → スレッド間を安全に共有可能
Arc(T) は Send + Sync を実装(スレッドセーフ参照カウント)

トレードオフ

利点

  1. 漸進的な採用:3層モデルが異なるスキルレベルに対応する
  2. 自然な構文:同期コードが並列性能を獲得する
  3. コンパイル時の安全性:Send/Sync 制約がデータ競合を消除する
  4. デバッグ可能性:エラーグラフが明確なエラー伝播ビューを提供する

欠点

  1. 学習曲線:DAG 依存の概念を理解する必要がある
  2. コンパイル時間:全プログラム DAG 解析は遅い可能性がある
  3. ツールチェーンの複雑性:新しいデバッグと可視化ツールが必要

代替案

方案選択しない理由
明示的な async/await のみサポート透過的な並行を実現できない
完全透過的な並行のみサポートユーザーが制御権を失う
Go スタイルの goroutine型安全性なし、コンパイル時チェック不可
L1 モードのみ並作モデルのコアバリューを放棄

実装戦略

段階的区分

  1. 段階 1 (v0.1):@block 同期モード、基本型
  2. 段階 2 (v0.2):FlowScheduler スケジューラー
  3. 段階 3 (v0.3):spawn ブロック、明示的な並行
  4. 段階 4 (v0.5):L3 完全透過、DAG 自動解析
  5. 段階 5 (v0.6):エラーグラフ、グラフデバッガー
  6. 段階 6 (v1.0):本番使用可能な最適化

依存関係

  • RFC-001 には外部依存なし(基本コア)
  • RFC-008(Runtime 並行モデル)→ 設計完了
  • RFC-011(泛型システム)→ 設計完了

リスク

  1. DAG 解析性能:全プログラム解析は O(n²) 可能性があり、最適化が必要
  2. ツールチェーンの欠如:デバッガーをゼロから開発する必要がある
  3. ユーザー受容性:透過的な並行性には適切なドキュメントが必要

設計決定記録

決定決定日付
3層並行アーキテクチャL1/L2/L3 漸進式2025-01-05
@block アノテーション位置戻り値型の後2025-01-05
DAG エラー伝播依存辺に沿って上流に伝播2025-01-06
DAG 性能最適化増分構築 + キャッシュ2025-01-06
ランタイム選択泛型 + コンパイル時注入2025-01-06
ノードインターフェース泛型 + 関数注入(trait なし)2025-01-06
エラーグラフメモリDAG は単一関数内でのみ構築2025-01-06
リソース競合検出DAG データフロー依存、ユーザーの変数渡し2025-01-06
リソース型システムResource マーキング + DAG 自動依存2026-01-06
L1/L2/L3 メンタルモデル3層抽象化、実装メカニズムではない2026-01-06
@auto アノテーション削除、デフォルト動作と重複2026-05-11
L1 自動フォールバック削除、動作が予測できない2026-05-11

付録:用語集

用語定義
並作モデルYaoXiang の並行パラダイム:同期構文、非同期の本質
DAG有向無環図、計算依存関係を記述
spawn@block スコープ内の制御可能な並行
@block同期アノテーション、並行最適化を無効化
@eager熱心な評価、依存関係の完了を待機
Resourceリソース型マーキング、操作が自動的に DAG 依存を構築
エラーグラフ可視化されたエラー伝播パス

参考文献