SlimePython PoC 0–11 ― Hybrid Bit-Exact Isolate 実証 deep-dive
実機(WSL2 / CPython 3.12.3 / RustPython 0.5.0 / wasmtime 40 / x86_64)で行った PoC 0–11 の実ソース・変換コード・実測・再現手順です。数字はすべて固定 CPython・同一マシンでの実測値。AI 罠 17(empirical claim 捏造)回避方針に従い、未測定範囲は 100% と主張しません。
あなたが書いた Python を、まったく同じ結果を出す Rust に変換するツール。出力が 1 ビットまで一致することを SHA-256 で証明。きれいに書き直す必要はなく、動的な部分は安全な Python サンドボックスでそのまま動かします。
Python を手で Rust に書き直すと挙動がズレますが、出力が SHA-256 で 1 ビット一致する Rust を生成。動的部分は CPython Isolate に委譲(固定ランタイムで 95-99%)、真の非決定性は明示 reject。PoC 40/40 bit-exact 実証済。
全 Python を Rust 化せず、静的核→純 Rust(100% bit-exact)/ 動的→決定論 CPython Isolate / 非決定性→reject の Hybrid Bit-Exact Isolate。「意味を理解しない、構造を転写する」を動的領域へ拡張 ― CPython 自身に意味を生成させる。
ソースを構造として Slot IR へ射影。動的領域は CPython を pin(PYTHONHASHSEED=0・固定 seed/clock・libm pin)した決定論 Isolate に委譲し canonical encoding で境界接続。AI 罠 17 回避ポリシー下、100% は静的領域にのみ約束。
📋 「このレベルで AI に質問」= 選んだ解像度に合った指示つきで、このページの解説をコピーします。お手元の AI(Claude · GPT · Gemini · Grok 等)に貼れば、その目線でさらに深掘りできます。
0. モデル(2 領域 + 2 tier)
| 領域 | 変換先 | 保証 |
|---|---|---|
| 静的領域 | Slot IR → 純 Rust | 構造的に bit-exact |
| 動的領域 | Python 断片のまま Deterministic CPython Isolate へ委譲 | 同一環境で bit-exact(矛盾は保存、reject は非決定性のみ) |
| tier | 実装 | 忠実度 | 速度 | 移植 |
|---|---|---|---|---|
| Full | CPython 静的 Isolate | 40/40 bit-exact | python3 同等以上 | x86_64/glibc |
| Light | RustPython → WASM | 19/20(差は例外文面) | ~3–6× | WASM/aarch64 へ移植可 |
0.5 §13 静的 lift ― 動的構文の条件付き受理
§14 Isolate に委譲する前段として、§13 Phase 1 は 4 種の HIGH 動的構文を bit-exact を保ったまま静的等価形に lowerします(新規 Step 1.5)。受理した構文は二重検証(Python original ≡ Python lowered、その上で Python ≡ native Rust ≡ WASI Rust)を通り通常パイプラインへ合流。50/50 lift + 25/25 reject = 75/75 PASS(WASI 三者一致)。MT19937・SHA-256 ランタイムは純 Rust 自家実装で外部 crate 依存ゼロ。
| lift カテゴリ | 受入条件(precheck) | lowering / Rust 出力 |
|---|---|---|
getattr(o,"x") / setattr / hasattr | 第 2 引数が string literal(変数 / f-string / runtime concat は REJECT) | 直接 attribute アクセスへ展開。hasattr/default-getattr 参照フィールドは Option<T> |
threading.Lock / Thread 逐次化 | with lock: の Lock no-op、または strict triple t = Thread(target=fn, args=tup); t.start(); t.join()(Condition/Event/Barrier/Queue/daemon/複数 start で join 介在せず は REJECT) | Lock を drop、Thread triple を fn(*tup) へ置換 |
random.seed(N) + random.randint | seed が コンパイル時整数定数(time/変数 seed/sample/gauss は REJECT) | CPython 互換 MT19937 + getrandbits + _randbelow を _pyrandom として埋込(外部 crate 依存ゼロ) |
type("Name", (Base,), {...}) 一発生成 | module top-level で 3 引数すべて compile-time constant(変数 name/動的 bases/非リテラル dict key/関数内/user metaclass は REJECT) | class Name(Base): ... へ展開。Rust は派生 struct ごとに親メソッド本体を copy |
本 Phase で扱わない(REJECT): eval/exec、実行時引数の動的 metaclass、任意 *args/**kwargs、globals()/locals()、C 拡張、seed なし random。Phase 2 候補: enumerable な __getattr__/__setattr__ override、module-load 時 1 回限りの monkey patching。
1. Isolate runner(全 PoC 共通・~20 行)
動的 Python 断片を、決定論制約下の埋め込み CPython にそのまま渡して実行。stdout を SHA-256 で python3 と突き合わせる。
// PoC 2/3 Isolate runner — PYTHONHASHSEED=0 固定、.py を埋込 CPython で実行
use pyo3::prelude::*;
fn main() {
std::env::set_var("PYTHONHASHSEED", "0");
std::env::set_var("PYTHONUNBUFFERED", "1");
let path = std::env::args().nth(1).unwrap();
let code = std::fs::read_to_string(&path).unwrap();
Python::with_gil(|py| {
if let Err(e) = py.run_bound(&code, None, None) { e.print(py); std::process::exit(1); }
let _ = py.run_bound("import sys\nsys.stdout.flush()", None, None);
});
}
動的サンプル例(§13 で reject だった構文も bit-exact)
# monkey patch + decorator + kwargs forwarding(PoC 2 #15) def add_log(fn): def wrapped(*args, **kwargs): return f"LOG:{fn(*args, **kwargs)}" return wrapped class Service: def compute(self, x): return x * 100 Service.compute = add_log(Service.compute) # 実行時クラス書換 print(Service().compute(7)) # LOG:700 — Python=Isolate で SHA-256 一致
2. 正しさ ― 累計 40/40 bit-exact
| PoC | 内容 | 結果 |
|---|---|---|
| 1 | Any 5 | 5/5 |
| 2 | *args/**kwargs + 動的 getattr/setattr + monkey 15 | 15/15 |
| 3 | 巷の実コード動的 20(metaclass / 記述子 / dataclass / generator / eval-exec …) | 20/20 |
3. Full tier 速度 ― 「遅い」はビルド構成の問題だった(PoC 4→6)
当初、埋め込みは hot loop で python3 より ~18–38% 遅かった(PoC 4 のクロスオーバー)。根本原因は 共有 libpython.so の PIC(GOT/PLT 間接化)。/usr/bin/python3 は libpython を静的埋め込み(非 PIC)していた(ldd に libpython 行なし)。
# PoC 6: ソースから静的ビルド = production レシピ(スタブ不要・PIE/ASLR 維持) ./configure --prefix=<pfx> --disable-shared --enable-optimizations --with-lto make -j$(nproc) && make altinstall # Isolate を静的 libpython にリンク(PyO3 shared=false / prepare_freethreaded_python 手動) PYO3_CONFIG_FILE=pyo3-source.cfg LIBPY_KIND=source cargo build --release
| M(work/launch) | iso_source / python3 |
|---|---|
| 1(短命) | 0.60×(速い) |
| 1,000,000(hot) | 0.99×(同等) |
共有 .so のみ 1.19–1.34× で遅い ― これを Py_BytesMain ランナー(CLI 完全同一経路)+ distro の非PIC/PIC/.so 3 variant で切り分け確定(PoC 4.5/5)。
4. Light tier ― RustPython → WASM(PoC 7/8)
同 20 サンプルで 19/20 bit-exact(唯一の差は abc 例外メッセージ文面、意味論は一致)。wasm32-wasip1 にクロスコンパイルし wasmtime で実行 ― wasm = native RustPython 20/20。CPython 埋め込みが不能な WASI を Light tier が完動。
5. 自動振り分け + 実行時プロファイル(PoC 9/10)
# PoC 9 router(静的): reject は非決定性のみ。誤ルート 0/20
if target in ("wasm","aarch64"): return Decision("light", "Full 不能")
if sig.unsupported: return Decision("full", "非対応")
if sig.exc_text_dep and exact_exceptions: return Decision("full", "例外文面の完全一致")
if sig.hot_loop and perf == "fast": return Decision("full", "hot loop 回避")
return Decision("light", "Light で十分")
PoC 10: 静的に出ない計算重(range(変数)・再帰)を実行時プロファイルで捕捉 → 次回 Full へ。hot_varrange Light 633ms→Full 212ms(3×)、hot_fib 1260ms→135ms(9×)。
6. reject 対象 = 非決定性のみ(PoC 11 実測 4 クラス)
| クラス | 例 | 扱い |
|---|---|---|
| A 既定で保全 | hash/set順(seed0)・dict・float演算・GIL threading | そのまま bit-exact |
| B Isolate注入で保全 | seedなし random・time | seed/clock 固定で決定論(値は正規化) |
| C 同一環境のみ保全 | os.environ・file I/O・subprocess | 同一環境では一致、環境間は CI 範囲 |
| D 真に非決定論 | id()・default repr(アドレス)・getpid・uuid4 | 保証対象外(= Python の性) |
「矛盾は保存、reject は非決定性のみ」。保全不能の核はメモリアドレス・プロセス ID・OS エントロピーの 3 種だけ。
7. ダウンロード(再現一式)
再現には CPython 3.12 / Rust 1.93 / PyO3 0.22 / RustPython 0.5 / wasmtime が必要。各 PoC ディレクトリの run_*.sh 参照。質問は お問い合わせへ。
