Files
sx/examples/0547-packs-xx-pack-index-to-protocol.sx
agra 8c47268539 fix: xx pack[i] to a protocol target heap-copies the element
Erasing a single comptime-pack element to a protocol value
(`xx sources[0]` with a protocol target) tripped the pack-as-value
error: buildProtocolErasure treated the index_expr as an lvalue and
took its address via lowerExprAsPtr, whose .index_expr arm lowers the
bare pack as a value (a pack is comptime-only with no runtime storage).

isLvalueExpr now reports a comptime pack index as an rvalue, decided
via the same packArgNodeAt predicate the value path uses — so the value
and lvalue paths can't diverge on what counts as a pack element — and
erasure heap-copies the already-materialized element instead.

Resolves issue 0135. Regression tests: examples/0547, 0548.
2026-06-13 18:55:10 +03:00

28 lines
1.0 KiB
Plaintext

// `xx <pack>[i]` erased to a protocol-typed local.
//
// Erasing a single comptime-pack element to a protocol scalar routes through
// buildProtocolErasure. A pack index is a comptime rvalue (a pack has no
// runtime storage — `sources[i]` resolves to the call-site arg, which only
// gets storage when lowered as a value), so the erasure must heap-copy the
// materialized element rather than take its address.
//
// Regression (issue 0135): `xx sources[0]` used to lower the bare pack as a
// value and error with "pack 'sources' has no runtime value".
#import "modules/std.sx";
VL :: protocol(T: Type) { get :: () -> T; }
IntCell :: struct { v: i64; }
impl VL(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
first :: (..sources: VL) -> i64 {
x : VL(i64) = xx sources[0]; // erase element 0 to VL(i64)
return x.get();
}
main :: () -> i32 {
print("{}\n", first(IntCell.{ v = 7 })); // 7
print("{}\n", first(IntCell.{ v = 42 }, IntCell.{ v = 99 })); // 42 (element 0)
0
}