{"atom":"regression/list-methods-no-copy","family":"regression","slug":"list-methods-no-copy","header":{"atom":"regression/list-methods-no-copy","kind":"whole-program — a minimal repro, not yet reduced to an atom","source":"curated"},"axes":null,"cols":null,"engines":["rakudo-2026.07","rakupp-3.14.0"],"kinds":["ref","pp"],"defFrom":"rakupp:t/regression/list-methods-no-copy.raku","counts":{"a":0,"f":0,"d":0,"c":0,"r":1,"n":0},"files":["atoms/regression/list-methods-no-copy.grid"],"records":[["0001","","# From the Cognates port (docs/rakupp-findings findings 2 and 3): `.elems`/`.end`/\n# `.Bool`/`AT-POS` and every array subscript materialised a COPY of the whole array\n# before answering, so one read was O(n) and a loop over an array was quadratic —\n# 20,000 reads of a 20,000-element array took 12.9 s against 8 ms for a lexical.\n# Those arms now read the live vector.\n#\n# This test guards the SEMANTICS the shortcut has to preserve; the speed is\n# covered by tools/perf-guard.raku. Contract: exit 0 + last line PASS.\nmy @fail;\nsub check($got, $want, $what) { @fail.push(\"$what: got {$got.raku} want {$want.raku}\") unless $got eqv $want }\n\nmy @a = 10, 20, 30;\ncheck(@a.elems, 3,     'elems');\ncheck(@a.end,   2,     'end');\ncheck(@a.Bool,  True,  'Bool on a populated array');\ncheck(@a.AT-POS(1), 20, 'AT-POS');\ncheck(@a.EXISTS-POS(2), True,  'EXISTS-POS in range');\ncheck(@a.EXISTS-POS(9), False, 'EXISTS-POS past the end');\ncheck(@a.AT-POS(-1), 30, 'AT-POS counts back from the end');\ncheck(@a.EXISTS-POS(-1), True, 'EXISTS-POS does too');\n\nmy @e;\ncheck(@e.elems, 0,      'elems of an empty array');\ncheck(@e.end,   -1,     'end of an empty array is -1');\ncheck(@e.Bool,  False,  'Bool of an empty array');\ncheck(@e.AT-POS(0).defined, False, 'AT-POS out of range is undefined');\ncheck(@e.AT-POS(0).^name, 'Any',  'and is an Any');\n\n# Reaching the array through a scalar container — an attribute, or a copy — must\n# give the same answers. This is the case the report hit.\nclass Holder { has @.items }\nmy $h = Holder.new(items => @a);\ncheck($h.items.elems, 3,  'elems through an attribute');\ncheck($h.items[1],    20, 'subscript through an attribute');\ncheck($h.items[*-1],  30, 'a Whatever subscript too');\nmy $copy = @a;\ncheck($copy.elems, 3,  'elems through a scalar');\ncheck($copy[2],   30,  'subscript through a scalar');\n\n# Slices still work, and still copy where they must.\ncheck(@a[0, 2].List,  (10, 30), 'an index-list slice');\ncheck(@a[1..2].List,  (20, 30), 'a Range slice');\ncheck(@a[^2].List,    (10, 20), 'a ^n slice');\n\n# The arms that MUTATE must still see a snapshot, not the live vector.\nmy @r = 1, 2, 3;\ncheck(@r.reverse.List, (3, 2, 1), 'reverse returns a reversed copy');\ncheck(@r.List,         (1, 2, 3), 'and leaves the original alone');\nmy @p = 1, 2, 3;\n@p.push(4);\ncheck(@p.elems, 4, 'push still grows the array');\ncheck(@p.pop,   4, 'pop returns the last element');\ncheck(@p.elems, 3, 'and shrinks it');\n\n# Ranges and lazy lists take the general path, not the shortcut.\ncheck((1..5).elems, 5, 'elems of a Range');\ncheck((1..5).Bool, True, 'Bool of a Range');\nmy $lazy = (1..Inf).map(* * 2);\ncheck($lazy[3], 8, 'a lazy list still indexes');\n\nif @fail { note \"FAILED:\\n\" ~ @fail.join(\"\\n\"); say 'FAIL' } else { say 'PASS' }","output PASS","r",["FAIL","PASS"],{"v":"disputed","w":"the reference implementation does not satisfy the program's own contract here (exit 0 with a last line of PASS) — it needs modules that are not installed, or exercises something only one engine implements; there is no reference observation to rule against","d":"2026-08-14 against rakudo-2026.07"},[["budget","20s"]]]]}