{"atom":"regression/callables-method-rw-capture-required","family":"regression","slug":"callables-method-rw-capture-required","header":{"atom":"regression/callables-method-rw-capture-required","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/callables-method-rw-capture-required.raku","counts":{"a":1,"f":0,"d":0,"c":0,"r":0,"n":0},"files":["atoms/regression/callables-method-rw-capture-required.grid"],"records":[["0001","","# Regression: routine introspection, `<->` blocks, Capture slipping, and two\n# exception messages.\n#   * `.yada` (a `{ ... }` / `{ !!! }` body) had no answer at all. `stmtIsStub`\n#     existed but was a lambda LOCAL to the class-declaration case, so only\n#     methods were ever asked. It is now file-scope and both the named-sub and\n#     the anonymous-sub Callable builders set the flag.\n#   * a statement-level `my method m(Int:D: $x) {…}` is a SubDecl with isMethod,\n#     but neither the parser's statement branch nor makeCand carried the flag, so\n#     callCallable never bound `self` and the invocant param found nothing —\n#     `self` in the body died, and `&m.^name` answered Sub.\n#   * `<->` (doubly-pointy) parsed exactly like `->` in expression position and\n#     never marked its params `is rw`, so the swap assigned to copies. The\n#     for-loop form got this right; the block and `whenever` forms did not.\n#   * `|$capture` slipped the Capture's NAMED parts as positionals: a Capture is\n#     an Array carrying hashKind \"Capture\" and took the plain Array branch, which\n#     pushes every element verbatim. `min |\\(1,7,3, by => {…})` then compared\n#     four values instead of three with a `:by`.\n#   * the assignment type-check message rendered the value with a bare `.gist`\n#     while the BINDING message quoted and elided it — two builders that had\n#     diverged. They now share one helper.\n#   * `is required(\"reason\")` dropped the reason: the parser's generic trait-\n#     argument skip ate the parenthesised text. Note Rakudo's exact shape — a\n#     comma and a NEWLINE before \"but\" when a reason is present, a comma and a\n#     space when it is not.\n# Contract: exit 0 + last line PASS.\nmy @fail;\nsub check($got, $want, $what) { @fail.push(\"$what: got $got want $want\") unless $got eq $want }\n\n# .yada\ncheck((sub f() { ... }).yada.gist, 'True',  'an anonymous stub');\ncheck((sub g() { 1 }).yada.gist,   'False', 'a real body is not a stub');\nsub h() { ... }\ncheck(&h.yada.gist,                'True',  'and a named one');\ncheck((sub k() { !!! }).yada.gist, 'True',  '!!! counts too');\n\n# a statement-level `my method`\nmy method m2(Int:D:) { 1 }\ncheck(&m2.^name, 'Method', 'it is a Method, not a Sub');\nmy method m(Int:D: $b) { self.^name }\ncheck(1.&m(<a>), 'Int', 'and self binds from the invocant');\n\n# `<->` marks its parameters rw\nmy $swap = <-> $a, $b { ($a, $b) = ($b, $a) };\nmy ($p, $q) = (2, 4);\n$swap($p, $q);\ncheck(\"$p $q\", '4 2', 'a doubly-pointy block writes back');\nmy $keep = -> $a, $b { ($a, $b) = ($b, $a) };\nmy ($r, $s) = (2, 4);\ntry { $keep($r, $s) };\ncheck(\"$r $s\", '2 4', 'a singly-pointy one still does not');\n\n# |$capture slips nameds as nameds\nmy $y = \\(1, 7, 3, by => { 1 / $_ });\ncheck(min(|$y), '7', 'the :by named survives the slip');\nsub t(*@p, *%n) { @p.raku ~ ' ' ~ %n.raku }\ncheck(t(|\\(1, 2, :x(3))), '[1, 2] {:x(3)}', 'positionals and nameds land in the right places');\ncheck(t(|(1, 2)),          '[1, 2] {}',      'a plain list is unaffected');\n\n# the two type-check messages agree\nmy $i of Int = 42;\ntry { $i = \"forty plus two\" }\ncheck($!.Str, 'Type check failed in assignment to $i; expected Int but got Str (\"forty plus two\")',\n      'the assignment message quotes a Str');\n\n# is required(\"reason\")\nclass RQ  { has $.a is required(\"it is a good idea\") }\nclass RQ2 { has $.a is required }\ntry { RQ.new }\ncheck($!.Str, \"The attribute '\\$!a' is required because it is a good idea,\\nbut you did not provide a value for it.\",\n      'the reason appears, with a newline before \"but\"');\ntry { RQ2.new }\ncheck($!.Str, \"The attribute '\\$!a' is required, but you did not provide a value for it.\",\n      'and the bare form is unchanged');\n\nif @fail { note \"FAILED: @fail.join('; ')\"; say 'FAIL' } else { say 'PASS' }","output PASS","a",["PASS","PASS"],0,[["budget","20s"]]]]}