Something went wrong. Try again.
Jam Programming Language jamlang.org
compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124// Fixed-size arrays OWN their elements: every drop-bearing element// drops exactly once when the array goes out of scope; bare named// locals MOVE into array literals (sources suppressed, use-after// rejected); repeat literals of drop-bearing values are rejected// outright (N owners of one payload). Regression: arrays previously// leaked every element.
const { assert } = import("test");
const Counter = struct { value: u32, sink: *mut u32,};
cfn drop(self: mut Counter) { var p: *mut u32 = self.sink; p.* = p.* + 1;}
const Pair = struct { slots: [2]Counter,};
fn arrayOfTemporaries(sink: *mut u32) { var arr: [3]Counter = [ Counter { value: 1, sink: sink }, Counter { value: 2, sink: sink }, Counter { value: 3, sink: sink }, ];}
tfn arrayElementsDropAtScopeExit() { var hits: u32 = 0; arrayOfTemporaries(&hits); assert(hits, 3);}
fn arrayOfNamedLocals(sink: *mut u32) { var c1: Counter = Counter { value: 1, sink: sink }; var c2: Counter = Counter { value: 2, sink: sink }; var arr: [2]Counter = [c1, c2];}
tfn namedLocalsMoveIntoArray() { var hits: u32 = 0; arrayOfNamedLocals(&hits); // sources suppressed, exactly the 2 elements drop assert(hits, 2);}
fn arrayInStructField(sink: *mut u32) { var p: Pair = Pair { slots: [ Counter { value: 1, sink: sink }, Counter { value: 2, sink: sink }, ] };}
tfn structFieldArrayDropsTransitively() { var hits: u32 = 0; arrayInStructField(&hits); assert(hits, 2);}
fn overwriteThenExit(sink: *mut u32) { var arr: [2]Counter = [ Counter { value: 1, sink: sink }, Counter { value: 2, sink: sink }, ]; arr[0] = Counter { value: 9, sink: sink };}
tfn elementOverwritePlusScopeExit() { var hits: u32 = 0; overwriteThenExit(&hits); // old arr[0] drops at the overwrite; both live elements drop at exit assert(hits, 3);}
fn nestedArrays(sink: *mut u32) { var m: [2][1]Counter = [ [Counter { value: 1, sink: sink }], [Counter { value: 2, sink: sink }], ];}
tfn nestedArrayElementsDrop() { var hits: u32 = 0; nestedArrays(&hits); assert(hits, 2);}
fn moveWholeArray(sink: *mut u32) { var arr: [2]Counter = [ Counter { value: 1, sink: sink }, Counter { value: 2, sink: sink }, ]; var owned: [2]Counter = arr;}
tfn wholeArrayMovesNotCopies() { var hits: u32 = 0; moveWholeArray(&hits); assert(hits, 2);}
// An array moved into a move param transfers whole-array ownership:// the callee drops the elements at exit, the caller is suppressed.fn consumeArr(arr: move [2]Counter) {}
fn makeAndMoveArr(sink: *mut u32) { var arr: [2]Counter = [ Counter { value: 1, sink: sink }, Counter { value: 2, sink: sink }, ]; consumeArr(arr);}
tfn arrayMoveParamDropsInCallee() { var hits: u32 = 0; makeAndMoveArr(&hits); assert(hits, 2);}