Skip to content

Merge train 28: dict keys of any hashable type (#594), ABI namespace jinja2::v2 (#604) - #606

Merged
rmorozov merged 22 commits into
masterfrom
claude/project-thread-53pwid
Oct 19, 2026
Merged

rmorozov merged 22 commits into
masterfrom
claude/project-thread-53pwid

Conversation

@rmorozov

@rmorozov rmorozov commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Integration train on master 9cf8586, merged with --no-ff in this order: #594 (0036), #604 (0076 PR-2, last as planned).

Conflicts resolved by the steward:

Task index and docs/parity.md (1995 templates) regenerated. Local: build clean, 4/4 ctest binaries pass.

Roles: no subagents except ci-triage for one red job; no verifier round on the train itself (owners ran theirs). Codex: #594 2 P1 (1 fixed, 1 declined on Ruslan's card), security review never started; #604 2 P2 fixed. Red pushes: 1 (clang-tidy readability-implicit-bool-conversion in the steward's own key-walk conflict resolution, fixed in b051f04); CI is green on that head.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DTQTriEsFrrBgcYNKDUUF4

claude added 22 commits October 18, 2026 11:25
KeyValuePair::key is an InternalValue; IMapAccessor gains GetKeyValues and
FindItem; MapRef/MapAdapter::GetKeys are gone. Every internal key reader
(repr, ==, list of a map, keys/values/items/copy/update, dictsort, pprint,
tojson, xmlattr, urlencode, dict(), pair targets) reads GetEntries or
GetKeyValues, with string fast paths kept.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
Reading a host map's entries copied every key into an owned value, and
dictsort's sort items grew by a value; Render/dict_ops was +5.9%.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
…g (0036)

Verifier round 1: hashing a key recursed through nested tuples without
a stack check, so a deeply nested tuple crashed where Python raises
RecursionError; and objects, which have no key token yet, matched the
empty-string key in lookups. The dict methods' cycle check also walks
non-string keys now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
Resolves conflicts with 0110's cycle collector: TemplateDict replaces
InternalDict in its walk, kept keys are walked and released too, and
setdefault/update note a stored key as well as the value.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
CI's gcc-12 Release build hashed the 20000-deep key without reaching the
stack limit, so the test now accepts Python's result or the recursion
error, and still catches a crash.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
The regeneration ran on Python 3.13, which words float modulo by zero
differently from the pinned CI interpreter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
Under TSan the 20000-level key walk overran the runtime's fixed-size
shadow call stack (from about 16000 levels, before the real stack ran
low), so __tsan_func_entry wrote past it and the run crashed inside
TSan. TSan builds now nest 10000 levels; ASan and plain builds keep
the full depth.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
A lazy tuple such as ('x',) * 2**40 reports items it never stores, and
hashing it as a dict key walked every one: the unhashable check and the
key token both bypassed the sequence cap. The check now counts the
items of all nested tuples against MaxSequenceSize and the token checks
its byte size per element, so such a key fails fast with 'too long'.

Found by Codex review on #594.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBh4wYzMbbA9rW6VkD5Lh7
…ce v2 (0076)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
Pure output of scripts/abi_namespace.py; no hand edits. Listed in
.git-blame-ignore-revs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
…abidiff (0076)

- format-check runs scripts/abi_namespace.py --check
- CTest jinja2cpp_abi_namespace: no jinja2 symbol outside v2, no global xyz
- test/package: abi_probe_v2 links, abi_probe_v1 (1.x mangling) must not
- check_package.cmake checks the installed SONAME; version asserts need major 2
- linux-build: one shared RelWithDebInfo row per standard dumps the ABI with
  abidw and reports abidiff against the last master build (baselines at the
  RC, task 0285)
- README: Compatibility and versioning; find_package(jinja2cpp 2)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
…anges

- gen_html_entities/unicode_case/unicode_tables/unicode_printable emit the
  inline namespace v2 form, so their --check matches the wrapped headers
- abi_report.sh: any change left after --no-added-syms is a break (abidiff
  reports a changed layout with bit 4, not 8); artifact uploaded on failure
- abi_namespace.py rejects spellings it does not rewrite (indented, one-line)
- docs/dependencies.md and SBOM name jinja2::v2::detail::xyz

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
MSVC does not implement CWG 2061: reopening namespace detail inside
namespace jinja2 declares a new jinja2::detail beside jinja2::v2::detail.
containers_api_test and node_arena_test now use the qualified form, and the
README tells 1.x detail::Reflector users to do the same.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
- check_package.cmake reads SOVERSION from CMakeLists.txt instead of using the
  project major, so a within-2.x SOVERSION bump installs and checks cleanly
- abi_report.sh gate fails while the committed baseline's SONAME differs from
  the library's, so a SOVERSION bump cannot land without its new baseline

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
The merge brought include/jinja2cpp/big_int.h in plain namespace jinja2;
scripts/abi_namespace.py wrapped it, which MSVC needs (CWG 2061).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua8ABM1TRsAvso2sWGHFSw
@rmorozov
rmorozov marked this pull request as ready for review October 19, 2026 09:34
@rmorozov
rmorozov merged commit 8030f97 into master Oct 19, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants