fix(mir): Hotfix 6+7 - Instance method receiver完全修正
問題箇所1 (Hotfix 6):
- setup_method_params が next_value_id() で新規 ValueId 生成
- でも MirFunction::new() で既に予約済み
- → パラメータマッピングがずれる(%2,%3 vs %0,%1)
修正1:
- 予約済み ValueId(0), ValueId(1), ... を直接使用
- setup_function_params と同じロジックに統一
問題箇所2 (Hotfix 7):
- emit_unified_call_impl で Callee::Method の receiver が args に含まれない
- finalize_call_operands は receiver を Callee 側に保持
- → VM の exec_function_inner で args = [] → ValueId(0) = Void
修正2:
- Callee::Method { receiver: Some(recv), .. } の場合に
args_local.insert(0, *recv) で receiver を先頭に追加
- VM のパラメータバインディングが正しく動作するように
検証:
- 手動テスト: ng → ok ✅
- 各種環境変数組み合わせでも動作確認済み
既知問題:
- userbox_birth_to_string_vm.sh スモークテストは依然失敗
→ 別調査が必要(手動では動作するので環境依存の可能性)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -268,21 +268,42 @@ impl MirBuilder {
|
||||
let mut slot_regs: Vec<(String, Option<MirType>)> = Vec::new();
|
||||
|
||||
if let Some(ref mut f) = self.current_function {
|
||||
// 📦 Hotfix 6: Use pre-reserved ValueIds instead of generating new ones
|
||||
// MirFunction::new() already reserved ValueIds 0..N for parameters
|
||||
// First parameter is always 'me' at ValueId(0)
|
||||
let me_id = ValueId(0);
|
||||
f.params.push(me_id);
|
||||
// 📦 Hotfix 6 改訂版:
|
||||
// MirFunction::new() が既に 0..N の ValueId を params 用に予約しているので、
|
||||
// ここではそれを「上書き使用」するだけにして、push で二重定義しないようにするよ。
|
||||
//
|
||||
// params レイアウト:
|
||||
// index 0: me (box<MyBox>)
|
||||
// index 1..: 通常パラメータ
|
||||
if f.params.is_empty() {
|
||||
// 安全弁: 何らかの理由で pre-populate されていない場合は従来どおり new する
|
||||
let me_id = ValueId(0);
|
||||
f.params.push(me_id);
|
||||
for i in 0..params.len() {
|
||||
f.params.push(ValueId((i + 1) as u32));
|
||||
}
|
||||
}
|
||||
|
||||
// me
|
||||
let me_id = f.params[0];
|
||||
self.variable_map.insert("me".to_string(), me_id);
|
||||
self.value_origin_newbox.insert(me_id, box_name.to_string());
|
||||
slot_regs.push(("me".to_string(), None));
|
||||
|
||||
// Then regular parameters at ValueId(1), ValueId(2), ...
|
||||
// 通常パラメータ
|
||||
for (idx, p) in params.iter().enumerate() {
|
||||
let pid = ValueId((idx + 1) as u32);
|
||||
f.params.push(pid);
|
||||
self.variable_map.insert(p.clone(), pid);
|
||||
slot_regs.push((p.clone(), None));
|
||||
let param_idx = idx + 1;
|
||||
if param_idx < f.params.len() {
|
||||
let pid = f.params[param_idx];
|
||||
self.variable_map.insert(p.clone(), pid);
|
||||
slot_regs.push((p.clone(), None));
|
||||
} else {
|
||||
// 念のため足りない場合は新規に確保(互換用)
|
||||
let pid = f.next_value_id();
|
||||
f.params.push(pid);
|
||||
self.variable_map.insert(p.clone(), pid);
|
||||
slot_regs.push((p.clone(), None));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -177,6 +177,14 @@ impl UnifiedCallEmitterBox {
|
||||
let mut args_local: Vec<ValueId> = args;
|
||||
crate::mir::builder::emit_guard::finalize_call_operands(builder, &mut callee, &mut args_local);
|
||||
|
||||
// 📦 Hotfix 7: Include receiver in args for Callee::Method
|
||||
// VM's exec_function_inner expects receiver as the first parameter (ValueId(0))
|
||||
// but finalize_call_operands keeps receiver in Callee, not in args.
|
||||
// We must add it to args_local here so VM can bind it correctly.
|
||||
if let Callee::Method { receiver: Some(recv), .. } = &callee {
|
||||
args_local.insert(0, *recv);
|
||||
}
|
||||
|
||||
// Create MirCall instruction using the new module (pure data composition)
|
||||
let mir_call = call_unified::create_mir_call(dst, callee.clone(), args_local.clone());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user