From cab98e2fb46816613f8f612a961efa758234dfae Mon Sep 17 00:00:00 2001 From: tomoaki Date: Thu, 25 Dec 2025 10:55:41 +0900 Subject: [PATCH] fix(rewrite): Extend primitive guards to include boxed primitives (Phase 287 P4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical fix: Guards only checked MirType::{Integer,Float,Bool,String} but missed MirType::Box("IntegerBox") etc. This caused .length().toString() to be rewritten to Global(Main.toString/0). Root cause: .length() returns boxed Integer (MirType::Box("IntegerBox")) not primitive Integer (MirType::Integer), so guards didn't catch it. Fix: Extended is_primitive check to include boxed primitive types: MirType::Box(name) if name in ["IntegerBox", "FloatBox", "BoolBox", "StringBox"] Modified functions in known.rs (all 4): 1. try_known_rewrite (line 61-65) 2. try_known_rewrite_to_dst (line 156-160) 3. try_unique_suffix_rewrite (line 256-260) 4. try_unique_suffix_rewrite_to_dst (line 332-336) MIR verification: - All toString() calls now use Method(IntegerBox.toString) ✅ - No more Global("Main.toString/0") calls ✅ Remaining issue (separate bug): - VM fails with "Unknown method 'toString' on Integer" - MIR is correct, problem is in VM Method call resolution - Needs separate investigation 🎉 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/mir/builder/rewrite/known.rs | 62 ++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/mir/builder/rewrite/known.rs b/src/mir/builder/rewrite/known.rs index 9f98aaa1..8c21d707 100644 --- a/src/mir/builder/rewrite/known.rs +++ b/src/mir/builder/rewrite/known.rs @@ -58,14 +58,16 @@ pub(crate) fn try_known_rewrite( if method == "toString" || method == "stringify" || method == "str" { if let Some(recv_type) = builder.type_ctx.value_types.get(&object_value) { use crate::mir::MirType; - match recv_type { - MirType::Integer | MirType::Float | MirType::Bool | MirType::String => { - if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { - eprintln!("[P287-GUARD] try_known_rewrite: BLOCKED primitive type {:?} for {}", recv_type, method); - } - return None; + let is_primitive = match recv_type { + MirType::Integer | MirType::Float | MirType::Bool | MirType::String => true, + MirType::Box(name) if name == "IntegerBox" || name == "FloatBox" || name == "BoolBox" || name == "StringBox" => true, + _ => false, + }; + if is_primitive { + if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { + eprintln!("[P287-GUARD] try_known_rewrite: BLOCKED primitive type {:?} for {}", recv_type, method); } - _ => {} + return None; } } } @@ -151,14 +153,16 @@ pub(crate) fn try_known_rewrite_to_dst( if method == "toString" || method == "stringify" || method == "str" { if let Some(recv_type) = builder.type_ctx.value_types.get(&object_value) { use crate::mir::MirType; - match recv_type { - MirType::Integer | MirType::Float | MirType::Bool | MirType::String => { - if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { - eprintln!("[P287-GUARD] try_known_rewrite_to_dst: BLOCKED primitive type {:?} for {}", recv_type, method); - } - return None; + let is_primitive = match recv_type { + MirType::Integer | MirType::Float | MirType::Bool | MirType::String => true, + MirType::Box(name) if name == "IntegerBox" || name == "FloatBox" || name == "BoolBox" || name == "StringBox" => true, + _ => false, + }; + if is_primitive { + if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { + eprintln!("[P287-GUARD] try_known_rewrite_to_dst: BLOCKED primitive type {:?} for {}", recv_type, method); } - _ => {} + return None; } } } @@ -249,14 +253,16 @@ pub(crate) fn try_unique_suffix_rewrite( if method == "toString" || method == "stringify" || method == "str" { if let Some(recv_type) = builder.type_ctx.value_types.get(&object_value) { use crate::mir::MirType; - match recv_type { - MirType::Integer | MirType::Float | MirType::Bool | MirType::String => { - if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { - eprintln!("[P287-GUARD] try_unique_suffix_rewrite: BLOCKED primitive type {:?} for {}", recv_type, method); - } - return None; + let is_primitive = match recv_type { + MirType::Integer | MirType::Float | MirType::Bool | MirType::String => true, + MirType::Box(name) if name == "IntegerBox" || name == "FloatBox" || name == "BoolBox" || name == "StringBox" => true, + _ => false, + }; + if is_primitive { + if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { + eprintln!("[P287-GUARD] try_unique_suffix_rewrite: BLOCKED primitive type {:?} for {}", recv_type, method); } - _ => {} + return None; } } } @@ -323,14 +329,16 @@ pub(crate) fn try_unique_suffix_rewrite_to_dst( if method == "toString" || method == "stringify" || method == "str" { if let Some(recv_type) = builder.type_ctx.value_types.get(&object_value) { use crate::mir::MirType; - match recv_type { - MirType::Integer | MirType::Float | MirType::Bool | MirType::String => { - if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { + let is_primitive = match recv_type { + MirType::Integer | MirType::Float | MirType::Bool | MirType::String => true, + MirType::Box(name) if name == "IntegerBox" || name == "FloatBox" || name == "BoolBox" || name == "StringBox" => true, + _ => false, + }; + if is_primitive { + if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") { eprintln!("[P287-GUARD] try_unique_suffix_rewrite_to_dst: BLOCKED primitive type {:?} for {}", recv_type, method); - } - return None; } - _ => {} + return None; } } }