// Phase 6 — pack-spread in a parameterized-type's arg list:
// `Combined($R, ..sources.T)`. Inside a pack-fn, `..sources.T` projects each
// source's protocol type-arg and spreads them into the generic struct's pack
// type-param `..$Ts`, so `Combined(s64, ..sources.T)` for a single `VL(s64)`
// source instantiates `Combined(s64, s64)` (field `sources: (VL(s64))`).

#import "modules/std.sx";

VL :: protocol(T: Type) { get :: () -> T; }
IntCell :: struct { v: s64; }
impl VL(s64) for IntCell { get :: (self: *IntCell) -> s64 => self.v; }

Combined :: struct($R: Type, ..$Ts: []Type) {
    sources: (..VL(Ts));
    value:   $R;
}

make :: (..sources: VL) -> s64 {
    c : Combined(s64, ..sources.T) = ---;   // instantiate with the spread type-arg
    c.sources.0 = xx sources[0];            // erase the concrete source to VL(s64)
    return c.sources.0.get();
}

main :: () -> s32 {
    print("{}\n", make(IntCell.{ v = 7 }));   // 7
    0;
}
