RFC-025: 拡張可能なプリミティブ型機構
概要
このドキュメントはYaoXiangコンパイラの拡張可能なプリミティブ型機構(Primitive::Extension)を定義します。外部コードがコンパイラにカスタムプリミティブ型を登録できるようにし、コンパイラがハードコードなしでドメイン固有型(量子ビット、GPUバッファ、SIMDベクトル、ハードウェアレジスタなど)をサポートできるようにします。
動機
なぜこの機構が必要か?
現在のコンパイラはすべてのプリミティブ型をハードコードしています:Int、Float、String、Bool、Unit。新しいプリミティブ型を追加するたびに、コンパイラのソースコードの複数の箇所(型チェッカー、コードジェネレータ、所有権アナライザ、オプティマイザ)を修正する必要があります。
これは開放閉鎖原則に反しています:拡張に対しては開放されていますが、修正に対しては開放されていません。
設計境界
ハードコードされたコア型(言語の基盤):Int, Float, String, Bool, Unit
動的に拡張される型(ドメインプラグイン): Primitive::Extension経由で登録コア型をハードコード的原因是、コンパイラがこれらのセマンティクスを深く依存しているからです(算術演算、条件分岐、ハッシュ、比較)。拡張型はコンパイラにとって不透明な値です——コンパイラはサイズ、アライメント、所有権属性のみ知り、内部セマンティクスは知りません。
これは「すべての型を動的ロードに統一する」ことではありません。コア型と拡張型は別々のものです。
提案
コア設計
1. Extension型属性
各拡張プリミティブ型は登録時に以下の属性を宣言する必要があります:
pub struct PrimitiveExtension {
/// 型名(例:"Qubit", "Buffer", "Vec128")
pub name: String,
/// バイトサイズ(固定サイズ型)
/// Noneはコンパイル時にサイズが不明であることを示す(実行時に決定が必要)
pub size: Option<usize>,
/// アライメント要件
pub align: Option<usize>,
/// 暗黙的なコピーを許可するかどうか
/// false = Moveセマンティクス(代入は移動、例:Qubit)
/// true = Copyセマンティクス(代入はコピー、例:Vec128)
pub is_copy: bool,
/// 空値(ゼロサイズ型)を許可するかどうか
pub allow_zst: bool,
}2. 登録インターフェース
// コンパイラの内部API
compiler.register_primitive(PrimitiveExtension {
name: "Qubit".to_string(),
size: Some(0), // 論理サイズは0、物理状態は量子プロセッサ上にある
align: Some(1),
is_copy: false, // Moveセマンティクス、no-cloningに準拠
allow_zst: true,
});登録後、Qubitは型システム内で合法的なプリミティブ型となり、変数宣言、関数パラメータ、構造体フィールドに使用できます。
3. 型チェッカーの動作
拡張プリミティブ型は型チェックで以下の規則に従います:
| シナリオ | 動作 |
|---|---|
変数宣言 q: Qubit = ... | ✅ 合法 |
関数パラメータ fn(q: Qubit) | ✅ 合法 |
構造体フィールド { q: Qubit } | ✅ 合法 |
is_copy == false 時の代入 | Moveセマンティクス、元変数は無効化 |
is_copy == true 時の代入 | Copyセマンティクス、元変数は保持 |
| 暗黙的なコピー(関数の複数使用) | is_copyに依存 |
比較 ==、!= | ❌ コンパイルエラー(組み込み比較なし) |
算術 +、- | ❌ コンパイルエラー(組み込み演算なし) |
ジェネリクス制約 T: Copy | is_copy == trueの場合のみ充足 |
4. コードジェネレータの動作
拡張プリミティブ型はコード生成で不透明な値として処理されます:
- LLVM IR:
{size} x i8または対応サイズの構造体として生成 - 特殊な命令は生成しない——セマンティクスはバックエンドまたはライブラリが担当
- バックエンドが特殊処理を必要とする場合(QIR量子ゲートなど)、バックエンド登録機構を通じて実装(本RFCの範囲外)
例
Moveセマンティクス型の登録
// 量子ビット:コピー不可、サイズは0(物理状態はQPU上にある)
compiler.register_primitive(PrimitiveExtension {
name: "Qubit".into(),
size: Some(0),
align: Some(1),
is_copy: false,
allow_zst: true,
});# ユーザーコード
q: Qubit = qubit(0)
q2 = q # ❌ コンパイルエラー:QubitはMove型、qは無効
q = H(q) # ✅ qを消費、新しいqを返すCopyセマンティクス型の登録
// SIMDベクトル:コピー可能、固定サイズ
compiler.register_primitive(PrimitiveExtension {
name: "Vec128".into(),
size: Some(16),
align: Some(16),
is_copy: true,
allow_zst: false,
});# ユーザーコード
a: Vec128 = load_vec128(data)
b = a # ✅ Copyセマンティクス、aは有効のまま
c = add_vec128(a, b) # ✅ aとbの両方を使用可能詳細な設計
コンパイラの改动
| コンポーネント | 改动 |
|---|---|
| 型システム | 新規 Ty::Extension バリアント、PrimitiveExtensionメタデータを格納 |
| 型チェッカー | 拡張型は組み込み演算解析に参加しない、組み込みトレイト制約を満たさない(明示的に実装した場合を除く) |
| 所有権アナライザ | is_copyに基づいてMoveまたはCopyセマンティクスを決定 |
| コードジェネレータ | size/alignに基づいて不透明値を生成、特殊命令なし |
| エラー情報 | 拡張型のエラーメッセージは登録時のnameを参照 |
FFIとの関係
Primitive::ExtensionとRFC-021(FFI)は直交しています:
| Primitive::Extension | FFI | |
|---|---|---|
| 役割 | 新規型を登録 | 外部関数を呼び出す |
| レベル | 型システム | ランタイム |
| 例 | Qubitは型である | native("sin")は関数呼び出しである |
1つのドメインが両方を必要とする場合があります:Qubit型はExtensionで登録し、量子ゲート関数はFFIで登録します。
後方互換性
- ✅ 完全な後方互換性
- 既存の型のセマンティクスを変更しない
- 拡張型は新規能力であり、既存コードに影響しない
トレードオフ
利点
- ✅ コンパイラが新しいドメインごとにソースコードを修正する必要がない
- ✅ ドメイン専門家がコンパイラチームに依存せずに型を登録できる
- ✅ コア型はハードコードされたままなので、コンパイラの基盤型に対する高度な最適化を犠牲にしない
- ✅ インターフェースはシンプル、1つの構造体で全属性を定義
欠点
- ⚠️ 拡張型は組み込み演算をサポートしない——セマンティクスを実装するには追加の関数またはバックエンド機構が必要
- ⚠️ デバッグ時に拡張型は不透明な値として表示され、コア型ほど直感的ではない
代替案
| 案 | 選択しない理由 |
|---|---|
| すべての型を動的ロード | コア型(Int/Float/Bool)はコンパイラの高度な最適化が必要、動的ロードではこれらの能力を失う |
| 各ドメインをハードコード | ドメインを追加するたびにコンパイラを修正、拡張性がない |
| 純粋ライブラリ案(型登録なし) | 型システムレベルでセマンティクス(no-cloningなど)を保証できず、実行時チェックのみ |
実装戦略
フェーズ1:コアインターフェース
- [ ] 型システムに
Ty::Extensionバリアントを追加 - [ ]
register_primitiveAPIを実装 - [ ] 型チェッカーが
is_copyセマンティクスを処理するよう拡張 - [ ] コードジェネレータが不透明値を処理するよう拡張
- [ ] ユニットテスト
フェーズ2:登録タイミング
- [ ] コンパイラ初期化時の批量登録をサポート(設定ファイルまたはbuilder API)
- [ ] 標準ライブラリの事前登録をサポート(
std.primitiveモジュールが拡張型定義をエクスポート)
依存関係
- ハード依存なし。他のRFCとは独立して実装可能。
開放問題
- [ ] 拡張型はトレイト実装をサポートすべきか(例:
QubitにカスタムQuantumGateトレイトを実装させる)? - [ ] RAIIセマンティクスの拡張型をサポートするためにライフサイクルフック(
on_dropなど)が必要か? - [ ] 設定ファイル形式:TOML、YAML、またはYaoXiang独自の設定構文(RFC-015参照)?
設計決定記録
| 決定 | 決定 | 理由 | 日付 |
|---|---|---|---|
| コア型を動的ロードしない | ハードコードを 유지 | コンパイラがコア型のセマンティクスに深く依存、動的化による收益はゼロ | 2026-06-05 |
| 拡張型を不透明値とする | セマンティクスを注入しない | セマンティクスはバックエンド/ライブラリが担当、コンパイラは型安全と所有権のみ保証 | 2026-06-05 |
| FFIと直交 | 統合しない | 型登録と関数呼び出しは異なる抽象レベル | 2026-06-05 |
