{"atom":"regression/control-warn-and-datetime-attrs","family":"regression","slug":"control-warn-and-datetime-attrs","header":{"atom":"regression/control-warn-and-datetime-attrs","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/control-warn-and-datetime-attrs.raku","counts":{"a":1,"f":0,"d":0,"c":0,"r":0,"n":0},"files":["atoms/regression/control-warn-and-datetime-attrs.grid"],"records":[["0001","","# Regression: two gaps JSON::Unmarshal's own test suite found (via the\n# `rakupp install` test gate, which refused the dist):\n#\n# 1. CONTROL { when CX::Warn } did not exist: `warn` printed straight to\n#    stderr, never raising an interceptable control exception. Now warn runs\n#    the innermost dynamically-enclosing CONTROL handler IN PLACE (no\n#    unwinding, so .resume is resumable by construction; the handler is\n#    popped while it runs, so its own warns escape outward). A handler that\n#    .resume's suppresses the default print; one that does not leaves the\n#    default behaviour standing. CONTROL blocks also no longer masquerade as\n#    CATCH — a real die passes straight through them.\n#\n# 2. DateTime.^attributes was empty (every builtin answered the honest empty\n#    list). JSON::Unmarshal rebuilds a DateTime from a JSON object shaped\n#    like Rakudo's internals ($!year … $!daycount, &!formatter), so Date and\n#    DateTime now answer the Rakudo-shaped list; all other builtins keep the\n#    empty answer.\n#\n# Every check verified against Rakudo (this file runs on both engines).\n#\n# Contract: exit 0 + last line PASS.\nmy @fail;\n\nsub check($got, $want, $desc) {\n    @fail.push(\"$desc: got {$got.raku}, want {$want.raku}\") unless $got eqv $want;\n}\n\n# ---- CONTROL / CX::Warn -----------------------------------------------------\n{\n    my $caught = '';\n    {\n        CONTROL {\n            when CX::Warn {\n                $caught = .message;\n                .resume\n            }\n        }\n        warn \"intercepted\";\n        $caught ~= \"|continued\";\n    }\n    check $caught, 'intercepted|continued', 'CONTROL sees CX::Warn, .resume continues after the warn';\n}\n\n{\n    my $caught = '';\n    sub deep-warner {\n        warn \"from a sub\"\n    }\n    {\n        CONTROL {\n            when CX::Warn {\n                $caught = .message;\n                .resume\n            }\n        }\n        deep-warner();\n    }\n    check $caught, 'from a sub', 'a warn inside a CALLED sub reaches the dynamically-enclosing CONTROL';\n}\n\n{\n    my $died = '';\n    try {\n        CONTROL {\n            when CX::Warn {\n                .resume\n            }\n        }\n        die \"real error\";\n    }\n    check ~$!, 'real error', 'a CONTROL block does not swallow a real die';\n}\n\n# ---- DateTime.^attributes ---------------------------------------------------\nmy @names = DateTime.^attributes.map(*.name);\ncheck @names.elems, 9, 'DateTime.^attributes answers all nine';\ncheck ?(@names.first(* eq '$!year')), True, '…including $!year';\ncheck ?(@names.first(* eq '&!formatter')), True, '…and &!formatter';\ncheck ?(DateTime.^attributes.first({ .has_accessor })), True, 'the flags satisfy introspection-driven rebuilds';\ncheck Date.^attributes.map(*.name).elems, 5, 'Date answers its five';\n# (Int would differ: Rakudo exposes its boxed $!value, rakupp's builtins\n# honestly answer empty — Any is attribute-free on both engines)\ncheck Any.^attributes.elems, 0, 'other builtins keep the empty answer';\n\nif @fail {\n    .say for @fail;\n    say \"FAIL\";\n    exit 1;\n}\nsay \"PASS\";","output PASS","a",["PASS","PASS"],0,[["budget","20s"]]]]}