fix(rewrite): Extend primitive guards to include boxed primitives (Phase 287 P4)
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 <noreply@anthropic.com>
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user