Implement targeted SocketBox Clone fix for shared mutable state

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-14 10:14:35 +00:00
parent 654e6692b0
commit 9572d0f321
5 changed files with 77 additions and 15 deletions

View File

@ -56,18 +56,14 @@ pub struct SocketBox {
impl Clone for SocketBox {
fn clone(&self) -> Self {
// Read the current state values atomically
let current_is_server = *self.is_server.lock().unwrap();
let current_is_connected = *self.is_connected.lock().unwrap();
// For listener and stream, we can't clone them, so we'll share them
// but create new Arc instances with the current state
// 🔧 FIX: Share state containers for "Everything is Box" reference sharing
// This ensures that clones of the same SocketBox share mutable state
Self {
base: BoxBase::new(), // New unique ID for clone
base: BoxBase::new(), // New unique ID for clone (for debugging/identity)
listener: Arc::clone(&self.listener), // Share the same listener
stream: Arc::clone(&self.stream), // Share the same stream
is_server: Arc::new(Mutex::new(current_is_server)), // New Arc with current value
is_connected: Arc::new(Mutex::new(current_is_connected)), // New Arc with current value
is_server: Arc::clone(&self.is_server), // 🔧 Share the same state container
is_connected: Arc::clone(&self.is_connected), // 🔧 Share the same state container
}
}
}

View File

@ -51,7 +51,8 @@ impl NyashInterpreter {
}
ASTNode::FieldAccess { object, field, .. } => {
self.execute_field_access(object, field)
let shared_result = self.execute_field_access(object, field)?;
Ok((*shared_result).clone_box()) // Convert Arc to Box for external interface
}
ASTNode::New { class, arguments, type_arguments, .. } => {
@ -672,7 +673,7 @@ impl NyashInterpreter {
/// フィールドアクセスを実行 - Field access processing with weak reference support
pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str)
-> Result<Box<dyn NyashBox>, RuntimeError> {
-> Result<SharedNyashBox, RuntimeError> {
// 🔥 Static Boxアクセスチェック
if let ASTNode::Variable { name, .. } = object {
@ -734,8 +735,8 @@ impl NyashInterpreter {
}
}
// Normal field access - convert Arc back to Box for compatibility
Ok((*field_value).clone_box())
// Return the shared Arc reference directly
Ok(field_value)
} else {
Err(RuntimeError::TypeError {
message: format!("Cannot access field '{}' on non-instance type. Type: {}", field, obj_value.type_name()),

20
test_basic_sharing.nyash Normal file
View File

@ -0,0 +1,20 @@
// Test basic field access sharing
static box Main {
init { mybox }
main() {
me.mybox = new IntegerBox(100)
print("=== Test 1: Basic field access ===")
local temp1
temp1 = me.mybox
print("temp1 ID: " + temp1.toString())
local temp2
temp2 = me.mybox
print("temp2 ID: " + temp2.toString())
// The IDs should be the same if sharing works
return temp1
}
}

21
test_box_id_sharing.nyash Normal file
View File

@ -0,0 +1,21 @@
// Test for Arc sharing - checking if same Box ID is returned
static box Main {
init { server }
main() {
me.server = new SocketBox()
print("=== First access ===")
local temp1
temp1 = me.server
print("Box ID: " + temp1.toString())
print("=== Second access ===")
local temp2
temp2 = me.server
print("Box ID: " + temp2.toString())
// If Arc sharing works, both should have same ID
return temp1
}
}

24
test_simple_arc_fix.nyash Normal file
View File

@ -0,0 +1,24 @@
// Simple test case to verify Arc sharing fix
static box Main {
init { counter }
main() {
me.counter = new IntegerBox(42)
print("=== Initial value ===")
print("counter: " + me.counter.to_string())
// Test if getting the same field returns the same object
local temp1
temp1 = me.counter
local temp2
temp2 = me.counter
print("=== Testing shared reference ===")
print("temp1: " + temp1.to_string())
print("temp2: " + temp2.to_string())
return me.counter
}
}