Files
sx/examples/issue-0008.sx
2026-03-05 16:20:36 +02:00

53 lines
1.7 KiB
Plaintext

// issue-0008: protocol value created in a function and appended to a list
// still stores a dangling stack pointer (issue-0007 fix incomplete)
//
// When a concrete value is converted to a protocol value inside a function
// (either implicitly via append or explicitly) and stored in a List, the
// protocol data pointer targets the function's stack frame instead of a
// heap-allocated copy.
//
// After the function returns, the first dispatch may succeed (stack not yet
// overwritten), but subsequent dispatches crash because the stack memory has
// been reused by other calls.
//
// STATUS: open — issue-0007 fix only covers some cases
#import "modules/std.sx";
Sizable :: protocol {
size :: () -> s64;
}
Leaf :: struct { value: s64; }
impl Sizable for Leaf {
size :: (self: *Leaf) -> s64 { self.value; }
}
add :: (items: *List(Sizable), w: Leaf) {
p := w;
items.append(p); // protocol value created from stack local `p`
}
main :: () -> void {
// Works: protocol value created in main, appended to list
out("=== Created in main ===\n");
list_a : List(Sizable) = .{};
s : Sizable = Leaf.{ value = 42 };
list_a.append(s);
r1 := list_a.items[0].size();
print("first: {} (expected 42)\n", r1);
r2 := list_a.items[0].size();
print("second: {} (expected 42)\n", r2);
// BUG: protocol value created in add(), first dispatch works, second crashes
out("=== Created in add() ===\n");
list_b : List(Sizable) = .{};
add(@list_b, Leaf.{ value = 99 });
r3 := list_b.items[0].size();
print("first: {} (expected 99)\n", r3); // works (stack not yet clobbered)
r4 := list_b.items[0].size();
print("second: {} (expected 99)\n", r4); // CRASH: stack memory reused
out("=== OK ===\n");
}