)]}'
{
  "log": [
    {
      "commit": "b4525d2bb0e1c0190d3d1bdf46711ee5dd1c4889",
      "tree": "3189ed7bd5a40451245dfe4390259d34e1d50445",
      "parents": [
        "71d177b8b7309de45deec02d17557ffe8aed52b4"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Thu Apr 30 12:11:14 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 30 12:11:14 2026 -0700"
      },
      "message": "fix(dataclass): collect py_class fields from plain bases (#575)\n\n## Summary\n\nFixes `@py_class` field collection when a decorated class inherits\nannotated fields through one or more non-`@py_class` Python bases.\n\nPreviously, `typing.get_type_hints(cls)` resolved inherited annotations,\nbut the field collector only iterated over annotations declared directly\non `cls`. A class such as `Add(BaseBinOp)` where `BaseBinOp` is a plain\nPython subclass of a registered FFI class would therefore register no\n`lhs` / `rhs` fields on `Add`, and construction failed with an\nunexpected keyword argument error.\n\nThis PR updates the collector to walk the current class MRO until the\nnearest registered FFI parent, collecting annotations from\nnon-registered Python bases as fields owned by the new type. The nearest\nregistered parent remains the TypeInfo boundary, so fields already\nregistered on `@py_class` ancestors are not duplicated.\n\nThe field merge now follows the review feedback from Gemini:\n\n- collection iterates owner classes from base to child,\n- `KW_ONLY` state is carried across the flattened non-FFI owner list,\n- fields are merged by name in insertion-order-preserving dictionaries,\nso an override keeps the original field position while adopting the\nmost-derived metadata.\n\nIt also updates class attribute installation to only preserve attributes\ndefined directly on the registered class. This prevents inherited plain\nPython defaults or `Field` sentinels from shadowing the reflected\nproperty descriptor installed for the child type.\n\n## Behavioral Impact\n\n- `@py_class` subclasses now accept fields declared on unregistered\nPython parents between the child and its registered FFI ancestor.\n- Field metadata from those plain parents is preserved, including\n`ClassVar`, `KW_ONLY`, and `init\u003dFalse` behavior.\n- Python multiple inheritance through non-FFI bases is covered as long\nas the class has a single registered FFI lineage.\n- More-derived field overrides preserve the first field position while\nreplacing metadata and type information.\n- No public API or ABI is added or removed.\n\n## Tests\n\n- `python -m ruff check tests/python/test_dataclass_py_class.py\npython/tvm_ffi/dataclasses/py_class.py python/tvm_ffi/registry.py`\n- `ty check tests/python/test_dataclass_py_class.py`\n- `python -m pytest tests/python/test_dataclass_py_class.py -q`\n- `python -m pytest tests/python/test_dataclass_enum.py\ntests/python/test_dataclass_common.py\ntests/python/test_dataclass_c_class.py\ntests/python/test_dataclass_init.py -q`\n\nAll checks passed locally.\n\nNote: the standalone `bug.py` reproducer is not present in this checkout\nafter the latest amendment, but the same construction path is covered by\n`test_collects_fields_from_non_py_class_parent`."
    },
    {
      "commit": "71d177b8b7309de45deec02d17557ffe8aed52b4",
      "tree": "990063a9b0553e1c9adac2f76be2827177354dd1",
      "parents": [
        "3c35034fd1026011736e19a4e0e1ed0f22058c42"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Thu Apr 30 10:28:27 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri May 01 01:28:27 2026 +0800"
      },
      "message": "chore(doc): Temp workaround missing pytorch docs (#577)\n\nWill switch back once https://docs.pytorch.org/docs/stable/objects.inv\nbecomes available again."
    },
    {
      "commit": "3c35034fd1026011736e19a4e0e1ed0f22058c42",
      "tree": "2a9bb3f1400cd417dbf55cd12cdc87dcb89dd4df",
      "parents": [
        "e472871900b80f1407d6880d103be4a874bb4084"
      ],
      "author": {
        "name": "Yaxing Cai",
        "email": "caiyaxing666@gmail.com",
        "time": "Mon Apr 27 03:31:02 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 26 15:31:02 2026 -0400"
      },
      "message": "[OrcJIT] Arena JITLinkMemoryManager with GOTPCRELX fix (Linux) (#527)\n\n## Summary\n\nAdds an arena-based `JITLinkMemoryManager` that eliminates\nscattered-mmap relocation overflow in LLVM ORC JIT under ASLR / VA\npressure ([LLVM\n#173269](https://github.com/llvm/llvm-project/issues/173269)), plus a\nworkaround for an x86_64 JITLink GOTPCRELX relaxation bug. Linux only;\nother platforms fall back to the default `InProcessMemoryManager`.\n\n### Arena memory manager (`orcjit_arena_mm.{h,cc}`)\n\n- Pre-reserves one contiguous VA region via `mmap(PROT_NONE |\nMAP_NORESERVE)` at session startup and bump-allocates from it,\nguaranteeing all JIT allocations stay within PC-relative range (±2 GB\nx86_64, ±4 GB AArch64).\n- Default capacity: 4 GB (x86_64) / 8 GB (AArch64). On reservation\nfailure (RLIMIT_AS, containers) the constructor halves down to a 256 MB\nfloor.\n- **Dual-pool split.** Arena is partitioned at a 2 MB-aligned midpoint\ninto a non-exec pool (`r--`/`rw-`) and an exec pool (`r-x`). Exec\nsegments pack tightly into whole 2 MB pages for contiguous r-x layout\nand TLB-friendly huge-page promotion. Both pools are capped so\ncross-pool Delta32 fixups always resolve inside ±2 GB.\n- **Slab commit with THP.** Physical pages are committed in 2 MB slabs,\nmatching Linux huge page size. `madvise(MADV_HUGEPAGE)` on the full\nreservation lets the kernel promote fully-faulted slabs to single TLB\nentries.\n- **Overflow sections.** Known large absolute-only sections\n(`.nv_fatbin`) are routed to separate `mmap()` allocations outside the\narena. Guarded by a two-phase check: name-based candidate selection,\nthen edge validation that disqualifies any section targeted by a\nPC-relative reference.\n- **Segment-lifetime handling.** `Finalize`-lifetime pages are freed at\nthe end of `finalize()`; `Standard`-lifetime pages remain until\n`deallocate()`. Free list coalesces adjacent blocks for reuse.\n- Decommit is deliberately a no-op: `ELFNixPlatform` deinitializers can\nstill reference freed allocations during teardown. Physical pages return\nto the free list instead; all memory is reclaimed by `munmap` in the\narena destructor.\n\n### GOTPCRELX fix plugin (`orcjit_session.cc`)\n\n- Works around LLVM JITLink\u0027s `optimizeGOTAndStubAccesses()` relaxing\n`call *foo@GOTPCREL(%rip)` → `addr32 call foo` but tagging the edge as\nabsolute `Pointer32`. On non-PIE executables with symbols in the low 4\nGB, this produces a garbage displacement → SIGSEGV during ORC-runtime\nteardown.\n- `GOTPCRELXFixPlugin` runs as a `PreFixupPass` after relaxation and\neither converts to `BranchPCRel32` when the displacement fits, or\nreverts the relaxation (restores `ff 15`/`ff 25` opcodes, retargets the\nedge to the GOT entry with `PCRel32`).\n\n### Configuration\n\n`ExecutionSession(arena_size\u003d...)` / `arena_size_bytes` C++ arg: `0` \u003d\narch default, `\u003e0` \u003d custom size, `\u003c0` \u003d disable arena. Linux-only;\nignored on macOS/Windows where the arena is compiled out.\n\n### Tests (`tests/test_arena.py`)\n\n8 arena tests across C/C++/GCC/PIE variants:\n\n- `test_arena_colocation` — objects stay within a small window.\n- `test_arena_keeps_objects_close` — scatter baseline under VA blocker\nwith arena enabled.\n- `test_arena_hidden_symbol_with_blocker` — ADRP/PC32 cross-object calls\nresolve under VA pressure.\n- `test_large_data_section` — 4 MB `.nv_fatbin` loads inside arena when\nreferences are absolute.\n- `test_overflow_section_outside_arena` — `.nv_fatbin` routed to\nseparate mmap, confirmed via address gap.\n- `test_dso_handle_relocation_after_failed_materialization` —\n`__dso_handle` resolves after prior sessions leaked slabs.\n- `test_dso_handle_delta32_with_arena` / `_overflow_without_arena` —\n`-fpie` GCC objects under 3 GB VA blocker: with arena → passes; without\narena → Delta32 overflow.\n\nAll tests use a 16 MB arena and 256 MB–3 GB VA blockers, safe for CI.\n\n## Test plan\n\n- [x] All orcjit tests pass locally on Linux x86_64 and aarch64\n- [ ] CI green on Linux x86_64, Linux aarch64, macOS arm64, Windows\nAMD64\n- [x] Non-Linux platforms unaffected (arena compiled out under `#ifdef\n__linux__`)\n\n---------\n\nCo-authored-by: Yaxing Cai \u003cyaxingc@gb-nvl-054-compute02.nvidia.com\u003e"
    },
    {
      "commit": "e472871900b80f1407d6880d103be4a874bb4084",
      "tree": "fe52e3bde90b6008b29b35d3640aff36a91668ab",
      "parents": [
        "899c5fb22cb41bed9e48ed259c6717d01757eb4d"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sun Apr 26 13:42:40 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 27 01:42:40 2026 +0800"
      },
      "message": "[FIX] Handle kTVMFFIRawStr / kTVMFFIByteArrayPtr in callback args path (#573)\n\n## Summary\n\n- **Bug**: When C++ invokes a Python callback with non-owning `RawStr`\nor `ByteArrayPtr` arg shapes, `TVMFFICyCallbackArgSetterFactory` (in\n`pycallback.pxi`) raised `ValueError` for both type indices, crashing\nthe callback immediately.\n\n- **Fix**: Add two new Cython setter functions —\n`TVMFFIPyCallbackArgSetterRawStr_` and\n`TVMFFIPyCallbackArgSetterByteArrayPtr_` — and register them in\n`TVMFFICyCallbackArgSetterFactory`. Each setter converts the non-owning\nC-side view to a Python `str` (UTF-8 decode) or `bytes` (memcopy) before\nreturning. Both non-owning views remain valid for the callback\u0027s\nduration, so there is no dangling-pointer concern.\n\n- **Why not change `make_ret`**: The return-value path (C-side\n`ffi::Function` invocation) never carries `kTVMFFIRawStr` /\n`kTVMFFIByteArrayPtr` because C++ normalises to owned variants\n(`ffi::String` / `ffi::Bytes`) before returning. The existing `raise\nValueError` arms in `make_ret` remain correct guards against an\nimpossible return-side type, exactly like the `kTVMFFIObjectRValueRef`\narm.\n\n- **Test**: One regression test in `tests/python/test_function.py`\n(`test_callback_rawstr_and_bytearrayptr_args`) uses\n`tvm_ffi.cpp.load_inline` to build a C++ shim with two trampolines:\n- `invoke_with_raw_str(callback)` — passes a C-string literal as `const\nchar*`, which `TypeTraits\u003cconst char*\u003e::CopyToAnyView` packs as\n`kTVMFFIRawStr` (with `v_c_str`).\n- `invoke_with_byte_array_ptr(callback)` — passes a stack\n`TVMFFIByteArray*`, which `TypeTraits\u003cTVMFFIByteArray*\u003e::CopyToAnyView`\npacks as `kTVMFFIByteArrayPtr` (with `v_ptr`).\nBoth paths are exercised in a single test body; the callback asserts it\nreceives a `str` / `bytes` with the expected content.\n\n## Files changed\n\n- `python/tvm_ffi/cython/pycallback.pxi` — two new setter functions +\nfactory registration\n- `tests/python/test_function.py` — one regression test + `import\ntvm_ffi.cpp`\n\n## Test plan\n\n- [ ] `uv run pytest -vvs tests/python/test_function.py` — 20 passed\n(was 19)\n- [ ] `uv run pytest tests/python` — 2303 passed, 5 skipped, 2 xfailed\n(3 pre-existing ROCm failures unrelated to this change)\n- [ ] `pre-commit run --files python/tvm_ffi/cython/pycallback.pxi\ntests/python/test_function.py` — all hooks passed"
    },
    {
      "commit": "899c5fb22cb41bed9e48ed259c6717d01757eb4d",
      "tree": "58014a13913af7b5007449bcb47337d1a47ce182",
      "parents": [
        "bc64ba3e981ae44a542ed4e7590320b15e530f57"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sat Apr 25 13:02:35 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 26 01:02:35 2026 +0800"
      },
      "message": "[REFACTOR] libinfo: add extra_lib_paths parameter for foreign-caller support (#570)\n\n## Summary\n\n`tvm_ffi.libinfo._find_library_by_basename(package, target_name)`,\n`load_lib_ctypes(...)`, and `load_lib_module(...)` now accept an\noptional\n`extra_lib_paths: list[Path] | None` parameter. Caller-supplied dirs\ntake\nprecedence over the existing `_rel_top_directory()` /\n`_dev_top_directory()`\nfallback. Self-call behavior unchanged.\n\nOn miss, the `RuntimeError` now lists every directory searched so\ndebugging\nis one error message away.\n\n## API\n\n```python\ndef load_lib_ctypes(\n    package: str,\n    target_name: str,\n    mode: str,\n    extra_lib_paths: list[Path] | None \u003d None,\n) -\u003e ctypes.CDLL: ...\n\ndef load_lib_module(\n    package: str,\n    target_name: str,\n    keep_module_alive: bool \u003d True,\n    extra_lib_paths: list[Path] | None \u003d None,\n) -\u003e Module: ...\n```\n\n`list[Path]` over `Sequence[Path | str]` — callers naturally produce\n`Path`\nobjects from `__file__`; single canonical type, no internal\nnormalization,\nfuture widening is non-breaking."
    },
    {
      "commit": "bc64ba3e981ae44a542ed4e7590320b15e530f57",
      "tree": "43bcf4d21dd71d07984c219bb065fdb4baad974e",
      "parents": [
        "96edb9a8fd0c474b311234b174719dda20230419"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sat Apr 25 12:57:01 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 26 00:57:01 2026 +0800"
      },
      "message": "[REFACTOR] Optimized Python callback path via TVMFFIPyCallbackArgSetter (#569)\n\nThis PR optimizes python callback specifically when the arguments expect\na torch.Tensor class.\n\n`tvm_ffi.convert_func(pyfunc, tensor_cls\u003dNone)` is provided. If\n`tensor_cls`\nis provided, the closure threads its `__dlpack_c_exchange_api__` capsule\ninto the callback so tensor args are delivered as `tensor_cls` instances\n(e.g., `torch.Tensor`) directly from the C-level setter — no per-arg\nPython-level conversion without python torch dlpack conversion overhead\n\nExample:\n\n```python\nimport torch\nimport tvm_ffi\n\ndef callback(a: torch.Tensor, b: torch.Tensor, c: torch.Tensor) -\u003e None:\n    # a, b, c arrive as torch.Tensor, converted in C via the closure\u0027s\n    # DLPack exchange API — no from_dlpack() needed inside the callback.\n    torch.add(a, b, out\u003dc)\n\nf \u003d tvm_ffi.convert_func(callback, tensor_cls\u003dtorch.Tensor)\n```\n\n| Variant                               | Per-call |\n|---------------------------------------|----------|\n| pycallback[tensor_cls\u003dtorch.Tensor]   | ~640 ns  |\n| pycallback+from_dlpack (explicit x3)  | ~9.1 us  |"
    },
    {
      "commit": "96edb9a8fd0c474b311234b174719dda20230419",
      "tree": "153fac40d4c0f9e85a3948df6e088d8293d36e51",
      "parents": [
        "02a344dbe6df51b8506194a2f56bea482274f90a"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Apr 24 02:20:59 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 24 02:20:59 2026 -0700"
      },
      "message": "feat(enum): add payload enum compatibility behavior (#568)\n\nTL;DR:\n- Make `IntEnum` and `StrEnum` variants behave like their raw payloads\nfor common Python enum operations while preserving FFI singleton\nidentity through same_as.\n\nExamples:\n- `Priority.low.name \u003d\u003d \"low\"` and `repr(Priority.low) \u003d\u003d\n\"Priority.low\"`.\n- `Priority.low \u003d\u003d 10`, `str(Priority.low) \u003d\u003d \"10\"`, and\n`hash(Priority.low) \u003d\u003d hash(10)`.\n- `Priority(10).same_as(Priority.low)` and\n`Priority(\"low\").same_as(Priority.low)`.\n- `Opcode(\"+\").same_as(Opcode.add)` and\n`Opcode(\"add\").same_as(Opcode.add)`.\n\nDetails:\n- Install payload-only instance dunders after `py_class`/`c_class`\ngeneration so payload semantics override generated object defaults\nwithout clobbering explicit user methods.\n- Gate payload behavior on `__ffi_enum_payload_value_type__` so plain\nEnum does not interpret arbitrary class-body values as public payloads.\n- Keep single-argument member lookup in `_EnumMeta.__call__` for\nexisting variants, raw payloads, and names.\n- Document why these methods are dynamically installed and what\nidentity/equality contract they preserve.\n- Add enum tests covering `name`, `repr`, `str`, `equality`, `hashing`,\nand construction from payload/name."
    },
    {
      "commit": "02a344dbe6df51b8506194a2f56bea482274f90a",
      "tree": "3f1dbb98848588f73c57a75bd5042efa5f273274",
      "parents": [
        "281f7e114fc46d262ccb57c18d19c7ef7b0a018c"
      ],
      "author": {
        "name": "Kathryn (Jinqi) Chen",
        "email": "65606304+Kathryn-cat@users.noreply.github.com",
        "time": "Fri Apr 24 00:08:39 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 24 00:08:39 2026 -0700"
      },
      "message": "feat: Added typed method registration for py_class (#567)\n\n## Add type method registration on py_class\n\nfeat(dataclasses): add @method decorator for FFI TypeMethod registration\n\nCloses the gap where `@py_class`-decorated Python classes couldn\u0027t\nexpose user-defined methods to the FFI reflection table. Trait\nreferences like `$method:NAME` in `__ffi_ir_traits__` now resolve\ncleanly against Python-defined methods, on parity with C++-defined\n`refl::ObjectDef\u003cT\u003e().def(\"name\", ...)`.\n\n## Architecture\n\n- `tvm_ffi.method` decorator stamps `fn.__ffi_method__ \u003d True` on the\n  decorated function (unwraps `staticmethod` to `__func__` so both\n  `@method @staticmethod` and `@staticmethod @method` work).\n- `_collect_py_methods` in `py_class.py` widens beyond the existing\n  `_FFI_RECOGNIZED_METHODS` allowlist: it now also picks up any\n  callable in `cls.__dict__` carrying the `__ffi_method__` marker\n  via `_is_method_marked`. The allowlist still routes TypeAttrColumn\n  dunders (`__ffi_repr__`, `__ffi_ir_traits__`, etc.) through\n  `TVMFFITypeRegisterAttr` unchanged.\n- Marked methods register through the existing TypeMethod path\n  (`TVMFFITypeRegisterMethod`) — same machinery the C++ side uses.\n  The C++ printer\u0027s `FindMethod` (`pyast_trait_print.cc:130-148`) walks\n  `info-\u003emethods[]` and discovers these entries identically to\n  C++-defined methods, including ancestor-walking for inheritance.\n- `_validate_method_name` rejects `@method` decoration on:\n  - `__ffi_*` reserved prefix (would double-register as TypeAttrColumn),\n  - Python protocol dunders (`__len__`, `__iter__`, etc. — reserved\n    for Python semantics),\n  - `@classmethod` (the `cls` first arg breaks the packed-call\n    convention; raises at decoration time).\n- Identity-typed: `@method` returns the original function unchanged\n  (no wrapping); IDE / type-checker sees the method\u0027s signature\n  unmodified.\n\n## Public Interfaces\n\n- `tvm_ffi.method` (re-exported from `tvm_ffi.dataclasses`)\n\n## Behavioral Changes\n\nNone for existing classes. Only NEW `@method`-decorated callables land\nin `TVMFFITypeInfo.methods[]`.\n\n## Tests\n\n- `tests/python/test_typed_method.py` (new, 13 tests): registration\n  shape, FFI Function callability, validation errors.\n- `tests/python/test_ir_traits.py` (5 new tests): end-to-end via\n`pyast.to_python()` against `$method:` refs in\n`AssignTraits.text_printer_post`,\n  `"
    },
    {
      "commit": "281f7e114fc46d262ccb57c18d19c7ef7b0a018c",
      "tree": "7a1bcc6936f37075ab5b4072559adf1ed1226f22",
      "parents": [
        "d70c905d16d16a93fedd7417e1500aaf11dfb530"
      ],
      "author": {
        "name": "Yaoyao Ding",
        "email": "dingyaoyao.cs@gmail.com",
        "time": "Fri Apr 24 01:20:07 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 23 22:20:07 2026 -0700"
      },
      "message": "doc: clarify structural_eq semantics and py_class eq/hash interaction (#566)\n\nRework the const-tree section in docs/concepts/structural_eq_hash.rst:\nthe \"Why not use it everywhere?\" example was bad — the drawn trees had\ndifferent pointers for their `+` nodes, so the const-tree pointer\nshortcut would never have fired. Replaced it with a shared-subtree\nscenario under `map_free_vars\u003dTrue` that actually exercises the bug, and\nexpanded \"When is this safe?\" with a third condition (interning payoff)\nplus a rule of thumb for choosing between `tree` and `const-tree`.\n\nExpand the `\"var\"` section to document that non-ignored fields on a var\ntype (e.g. a type annotation) are compared on first encounter but\nsubsequent occurrences short-circuit through the bijective mapping —\ni.e. the mapping is sticky.\n\nClarify the py_class docstring so readers understand that\n`structural_eq` is independent of `eq` / `unsafe_hash`: the default\n`__eq__` / `__hash__` remain pointer-based (inherited from `Object`),\nwhile `structural_equal` / `structural_hash` are driven separately by\nthe kind metadata registered in C++.\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) \u003cnoreply@anthropic.com\u003e\nCo-authored-by: gemini-code-assist[bot] \u003c176961590+gemini-code-assist[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "d70c905d16d16a93fedd7417e1500aaf11dfb530",
      "tree": "3393cf672018b2da068d6ba44194d8922347aea2",
      "parents": [
        "09e7216697307aaf454c041a9d527bd88f9986ee"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 21 09:35:03 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 21 09:35:03 2026 -0700"
      },
      "message": "refactor(enum)!: hide identity fields, add IntEnum/StrEnum, consolidate accessors (#564)\n\n## Summary\n\nThis PR completes the enum identity-vs-payload separation: it hides the\nintrinsic `_value` / `_name` fields, introduces `IntEnum` / `StrEnum`\npayload bases, consolidates the class-level entry accessors into a\nsingle `all_entries()` iterator, and adds a payload-aware fast path in\nthe Cython type converter so `py_class` fields typed as a payload-enum\naccept raw `int` / `str` values.\n\n## Architecture\n\n- **Rename `EnumObj::value` / `name` to `_value` / `_name`** across the\nC++ layout, reflection schema (`ObjectDef\u003cEnumObj\u003e::def_ro`), repr\nprinter, and `reflection::EnumDef`. The leading underscore frees the\npublic `value` symbol for user payload fields while keeping the dense\nordinal and declaration-key as the canonical variant identity.\n- **Add `IntEnum` / `StrEnum` base classes** in\n`tvm_ffi.dataclasses.enum` that reserve a declared `value: int` (resp.\n`str`) payload field via `_prepare_payload_enum_subclass`. The helper\ninjects or validates the `value` annotation *before*\n`Enum.__init_subclass__` runs, so reflection sees the payload as a\nfirst-class declared field rather than an extensible attribute, and\nstamps `__ffi_enum_payload_value_type__` onto the class for downstream\ndispatch.\n- **Tighten `py_class` parent-info lookup** to fall back to\n`base.__tvm_ffi_type_info__` when the core registry lookup misses, so\nPython subclasses descending through `IntEnum` / `StrEnum` register with\nthe correct parent type info.\n- **Consolidate class-level entry accessors** into a single\n`all_entries()` iterator backed by `_ordered_entries`. The `by_name` /\n`by_value` descriptors and the older `entries()` method are removed;\n`_EnumMeta.__iter__` / `__len__` and the public accessor now share one\ncanonical ordering path.\n- **Accept payload-literal variant declarations** on `IntEnum` /\n`StrEnum` (`red \u003d 10`, `add \u003d \"+\"`) as sugar for `entry(value\u003d...)`.\n`_collect_entry_declarations` treats bare assignments on payload enums\nas `_EnumEntry` values, and invalid payload types surface as a\n`TypeError` via the new `_instantiate_entry` error-normalizing wrapper.\n- **Payload-aware Cython dispatch**: new `_tc_convert_int_enum` /\n`_tc_convert_str_enum` inspect the registered target class\u0027s MRO at\nschema-build time and, at call time, coerce raw `int` / `str` payloads\ninto the matching variant via `all_entries()`. The object-passthrough\nand pack/convert fallback are preserved by factoring the marshaled path\ninto `_tc_convert_object_marshaled`.\n\n## Public Interfaces (BREAKING)\n\n- **C++ ABI break**: `EnumObj::value` / `EnumObj::name` no longer exist;\nconsumers must read `EnumObj::_value` / `EnumObj::_name`.\n- **Python API break**: on plain `Enum` subclasses, `instance.value` /\n`instance.name` are no longer surfaced (they raise `AttributeError`).\nUse `_value` / `_name` for the intrinsic ordinal and key, or migrate to\n`IntEnum` / `StrEnum` to obtain a user-visible `value` payload.\n- **Python API break**: `Enum.entries()` is renamed to\n`Enum.all_entries()`; `Enum.by_name` and `Enum.by_value` class\nproperties are removed. Replace `Cls.entries()` with\n`Cls.all_entries()`, `Cls.by_value` with `list(Cls.all_entries())`, and\n`Cls.by_name` with `{e._name: e for e in Cls.all_entries()}`.\n- **New exports**: `tvm_ffi.dataclasses.IntEnum` and\n`tvm_ffi.dataclasses.StrEnum` (added to `__all__`).\n- `entry(...)` now rejects `_value\u003d` / `_name\u003d` kwargs (previously\n`value\u003d` / `name\u003d`).\n- `IntEnum` / `StrEnum` subclasses additionally accept `red \u003d 10` / `add\n\u003d \"+\"` as sugar for `entry(value\u003d...)`.\n- `py_class` fields typed as `IntEnum` / `StrEnum` subclasses now accept\nraw `int` / `str` payloads at construction and assignment; the converter\nresolves them to the singleton variant and rejects unknown payloads with\nthe usual `expected \u003cType\u003e` error.\n\n## Behavioral Changes\n\n- Reading `.value` / `.name` on a plain `Enum` variant raises\n`AttributeError`.\n- Repr still produces `\u003ctype_key\u003e.\u003c_name\u003e` (wire-identical).\n- `iter(EnumCls)` and `len(EnumCls)` now route through\n`_ordered_entries` instead of the removed `by_value` descriptor;\nobservable ordering is unchanged (dense ordinal order).\n- Constructing an enum subclass with an invalid literal payload (e.g.,\n`class Bad(IntEnum): nope \u003d \"x\"`) now raises `TypeError` with a\n`\u003cCls\u003e.\u003cname\u003e: invalid enum entry: ...` prefix via `_instantiate_entry`,\nrather than leaking the raw converter error.\n- `py_class` field assignments of the form `inst.priority \u003d 20` (where\n`priority: Priority` is an `IntEnum`) now succeed, binding to the\ncorresponding enum variant.\n- **Python 3.8/3.9 compatibility**: `_prepare_payload_enum_subclass`\nuses `_own_annotations(cls)` rather than `getattr(cls,\n\"__annotations__\", {})`. The previous lookup followed MRO when the\nsubclass had no annotations of its own and pulled in the parent `Enum`\u0027s\n`_value` / `_name`, which then re-registered those fields on the\nsubclass and produced `ValueError: duplicate parameter name: \u0027_value\u0027`\nwhen constructing the `inspect.Signature` for `__init__`. Python 3.10+\nwas unaffected because the interpreter always materializes an empty\n`__annotations__` dict in every class body.\n\n## Docs\n\n- Doxygen and Python docstrings updated in-place in\n`include/tvm/ffi/enum.h`, `include/tvm/ffi/reflection/enum_def.h`,\n`include/tvm/ffi/reflection/accessor.h`, and\n`python/tvm_ffi/dataclasses/enum.py`.\n- No doc-site page referenced the old public `EnumObj::value` / `name`\nor the removed `entries()` / `by_name` / `by_value` accessors (verified\nvia `rg` over `docs/`), so no further changes in `docs/` were required.\n\n## Test plan\n\n- [x] `uv pip install --force-reinstall --verbose -e .` rebuild after\nCython changes in `pyclass_type_converter.pxi`.\n- [x] `uv run pytest -vvs tests/python/test_dataclass_enum.py\ntests/python/test_dataclass_py_class.py\ntests/python/test_type_converter.py` — 1008 passed, 2 xfailed.\n- [x] New tests:\n- `test_int_enum_payload_literal_sugar`,\n`test_str_enum_payload_literal_sugar`,\n`test_payload_literal_sugar_preserves_annotated_field_defaults`,\n`test_int_enum_payload_literal_sugar_rejects_invalid_payload`,\n`test_str_enum_payload_literal_sugar_rejects_invalid_payload`.\n- `test_all_entries_iteration_order`,\n`test_all_entries_indexed_by_ordinal` (replacing the removed\n`test_by_name_is_live_dict` / `test_by_value_indexed_by_ordinal`).\n- `test_public_value_and_name_are_hidden` (identity-hidden assertion on\nplain `Enum`).\n- `test_int_enum_payload_value` / `test_str_enum_payload_value`\n(end-to-end payload).\n- `TestPayloadEnums` group in `test_type_converter.py` covering int/str\npayload conversion, object passthrough, and rejection of unknown\npayloads.\n- `test_payload_enum_fields_end_to_end` in `test_dataclass_py_class.py`\ncovering construction, assignment, and error behavior for `IntEnum` /\n`StrEnum`-typed `py_class` fields.\n- [x] Python 3.8 MRO-lookup behavior reproduced on CPython 3.8.20 and\nthe `_own_annotations` fix validated against it.\n- [ ] CI C++ tests for `refl::EnumDef` (Linux x86_64/aarch64, macOS\narm64, Windows) — not rerun locally; relying on CI to exercise the\nrenamed `_value` / `_name` compile path.\n- [ ] CI Rust job — no local Rust coverage for downstream `EnumObj`\nfield consumers.\n- [ ] Cross-language (C++-backed) `IntEnum` / `StrEnum` payload coercion\nis not specifically exercised; existing `test_cxx_backed_*` cases cover\nthe object-passthrough path, and the new literal-sugar path targets\npure-Python subclasses.\n\n## Migration\n\n- Replace `enum_instance.value` / `.name` with `._value` / `._name`,\n**or** switch the base class to `IntEnum` / `StrEnum` to keep a\nuser-visible `value` field.\n- Replace `entry(value\u003d..., name\u003d...)` with `entry(_value\u003d...,\n_name\u003d...)`, or drop them (both are auto-assigned).\n- Replace `Cls.entries()` with `Cls.all_entries()`.\n- Replace `Cls.by_value` with `list(Cls.all_entries())`.\n- Replace `Cls.by_name` with `{e._name: e for e in Cls.all_entries()}`."
    },
    {
      "commit": "09e7216697307aaf454c041a9d527bd88f9986ee",
      "tree": "20268c1a81387d081a82b43876773b4cad3d6bde",
      "parents": [
        "68b06e9e45a1daa0180994aab1d7ed2695e257b1"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 21 09:34:52 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 21 09:34:52 2026 -0700"
      },
      "message": "fix(container): align sequence equality and contains (#560)"
    },
    {
      "commit": "68b06e9e45a1daa0180994aab1d7ed2695e257b1",
      "tree": "ca3c6ca6d484351a455eea55a545d864ca960676",
      "parents": [
        "24054b47bd013398e2c7bacb312f2d5e21059d50"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 20 19:50:46 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 20 19:50:46 2026 -0700"
      },
      "message": "fix(dataclass): distinguish containers from dataclasses (#557)"
    },
    {
      "commit": "24054b47bd013398e2c7bacb312f2d5e21059d50",
      "tree": "017c08356e2294d1c5251ea1932266e70a02e32d",
      "parents": [
        "7055626763b3e76c60842274286e10bde0f464ad"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Mon Apr 20 18:41:22 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 20 18:41:22 2026 -0400"
      },
      "message": "[FEAT] Enhance map_dataclass_to_tuple with JIT unpack_dataclass_to_tuple (#563)\n\nThis PR introduces an optimized unpack_dataclass_to_tuple util and\nreplaces `dataclasses.astuple` in `map_dataclass_to_tuple`, a\nJIT-compiled per-class unpacker that brings 5-11x speedup and does not\ndeep-copy leaf values.\n\nNot deep-copying leaf is important for runtime use-cases, when dataclass\nfields contain tensor objects or other large resources that must not be\ncopied -- leaf values are passed through by reference, not duplicated.\n\n## Design\n\n`unpack_dataclass_to_tuple(x)` recursively converts dataclass instances\nto tuples via JIT-compiled inline attribute access:\n\n- `_extract_dataclass_to_tuple_schema(cls)` -- inspect type annotations\n- `_validate_dataclass_to_tuple_schema(schema)` -- codegen security\n- `_compile_dataclass_to_tuple_schema(prefix, schema)` -- inline code\n\nCached per-thread (TLS) for thread safety. Conservative field\nclassification: only marks as leaf when certain (known primitives,\ncontainers of known primitives). Unknown types use dynamic dispatch.\n\n## Performance (vs dataclasses.astuple)\n\n| Case              | unpack | astuple | speedup |\n|-------------------|--------|---------|---------|\n| Config (2 flat)   | 144 ns |  769 ns |   5.3x  |\n| Nested (int + dc) | 152 ns | 1386 ns |   9.1x  |\n| Wide (5 flat)     | 170 ns | 1268 ns |   7.5x  |\n| Deep (2 levels)   | 200 ns | 2305 ns |  11.5x  |\n| WithAny (dynamic) | 254 ns | 1644 ns |   6.5x  |"
    },
    {
      "commit": "7055626763b3e76c60842274286e10bde0f464ad",
      "tree": "95f64a0c687a848d96db81aa95e66cb16da20687",
      "parents": [
        "fc6cf8a0596b6cc1a7f3b453d18bab3c60310622"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 20 12:40:52 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 20 12:40:52 2026 -0700"
      },
      "message": "fix(dataclass): resolve cross-module forward refs (#559)"
    },
    {
      "commit": "fc6cf8a0596b6cc1a7f3b453d18bab3c60310622",
      "tree": "48e1bac32f5fa2e2fb6383f60589d8ab252a26f2",
      "parents": [
        "6066f605558ec4bbc9d477e46894439edef60022"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 20 12:29:20 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 20 12:29:20 2026 -0700"
      },
      "message": "fix(enum): add class iteration and len (#558)"
    },
    {
      "commit": "6066f605558ec4bbc9d477e46894439edef60022",
      "tree": "8dd5d85162ac3713241bf26cb9a56598c8bf918c",
      "parents": [
        "9c4f59878ba11950eaae22fa50d2d6a3c9322043"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Apr 18 14:41:32 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Apr 18 14:41:32 2026 -0700"
      },
      "message": "feat(core): Introduce Attribute-Carrying Language-Agnostic Enums (#554)\n\nRFC: https://github.com/apache/tvm-ffi/issues/553\n\nAdd first-class cross-language enum support to TVM-FFI. An enum is a\nregistered Object type whose instances are named, frozen singletons —\nthe same model as `tvm::Op`, generalised into an `Enum` base class\nusable from Python and C++ and converging on a single shared registry\nper `type_key`.\n\n## At a glance\n\n### Python\n\n```python\nfrom __future__ import annotations\n\nfrom typing import ClassVar\n\nfrom tvm_ffi.dataclasses import Enum, auto, entry\n\n\n# Pure-Python enum — fresh type_key, no C++ involvement.\nclass Priority(Enum, type_key\u003d\"my.Priority\"):\n    low \u003d auto()\n    medium \u003d auto()\n    high \u003d auto()\n\n\n# Attribute-carrying enum.\nclass Activation(Enum, type_key\u003d\"nn.Activation\"):\n    output_zero: bool\n    is_monotonic: bool\n\n    relu: ClassVar[Activation] \u003d entry(output_zero\u003dTrue, is_monotonic\u003dTrue)\n    gelu: ClassVar[Activation] \u003d entry(output_zero\u003dFalse, is_monotonic\u003dFalse)\n    silu: ClassVar[Activation] \u003d entry(output_zero\u003dFalse, is_monotonic\u003dTrue)\n\n\n# Python class binding C++-registered entries.\nclass Variant(Enum, type_key\u003d\"testing.TestEnumVariant\"):\n    Alpha: ClassVar[Variant]   # bound to the C++-registered \"Alpha\"\n    Beta:  ClassVar[Variant]   # bound to the C++-registered \"Beta\"\n\n\nassert Activation.relu.value \u003d\u003d 0          # auto-assigned ordinal\nassert Activation.relu.name \u003d\u003d \"relu\"      # auto-populated\nassert Activation.relu.output_zero is True # user field\nassert Activation.get(\"relu\") is Activation.relu\n\n# Extensible per-variant attributes, writable from anywhere.\ncost \u003d Activation.def_attr(\"cost\", default\u003d0)\ncost[Activation.relu] \u003d 1\ncost[Activation.gelu] \u003d 4\nassert cost[Activation.silu] \u003d\u003d 0          # default — silu was never assigned\nassert Activation.silu not in cost         # distinguishes default-hit vs. set\n```\n\n### C++\n\n```cpp\n#include \u003ctvm/ffi/enum.h\u003e\n#include \u003ctvm/ffi/reflection/enum_def.h\u003e\n\nclass ActivationObj : public tvm::ffi::EnumObj {\n public:\n  bool output_zero;\n  bool is_monotonic;\n  TVM_FFI_DECLARE_OBJECT_INFO_FINAL(\"nn.Activation\", ActivationObj, tvm::ffi::EnumObj);\n};\n\nTVM_FFI_STATIC_INIT_BLOCK() {\n  namespace refl \u003d tvm::ffi::reflection;\n  refl::ObjectDef\u003cActivationObj\u003e(refl::init(false))\n      .def_ro(\"output_zero\", \u0026ActivationObj::output_zero)\n      .def_ro(\"is_monotonic\", \u0026ActivationObj::is_monotonic);\n\n  refl::EnumDef\u003cActivationObj\u003e(\"relu\")\n      .set_attr(\"output_zero\", true)\n      .set_attr(\"is_monotonic\", true);\n  refl::EnumDef\u003cActivationObj\u003e(\"gelu\")\n      .set_attr(\"output_zero\", false)\n      .set_attr(\"is_monotonic\", false);\n}\n```\n\nThe Python and C++ halves write to the same two `type_index`-keyed\nTypeAttr columns, so a Python subclass that binds\n`type_key\u003d\"nn.Activation\"` sees every C++-registered entry, and any\nlater `auto()`/`entry(...)` from Python becomes visible to C++ readers\nof the same columns. Entries cross FFI as ordinary `ObjectRef`s — no\nwire-format work.\n\n## Design\n\n- Enum instances are `EnumObj` subclasses. Each carries a dense\nauto-assigned `int64_t value` (0-indexed per class, declaration-order\nordinal) and a `String name`. Both are populated at registration;\nneither is user-supplied.\n- Two per-class TypeAttr columns, shared across all call sites:\n- `__ffi_enum_entries__` — `Dict\u003cString, Enum\u003e` mapping instance name →\nfrozen singleton.\n- `__ffi_enum_attrs__` — `Dict\u003cString, List\u003cAny\u003e\u003e` mapping attribute\nname → ordinal-indexed list.\n- **Register-once-then-mutate.** Each column is registered exactly once\nvia `TVMFFITypeRegisterAttr`; every subsequent writer fetches the live\ncontainer with `TVMFFIGetTypeAttrColumn` and mutates it in place.\nDistributed registration across TUs or Python modules converges on one\nset of containers.\n- **Python variants** are declared in one of four shapes, processed in\n`Enum.__init_subclass__`:\n1. `name: ClassVar[Cls] \u003d entry(**kwargs)` — registers a Python-side\nentry and forwards kwargs to `__init__`.\n2. `name \u003d entry(**kwargs)` (no annotation) — same as 1, for\nattribute-carrying enums where `ClassVar` is noise.\n3. `name \u003d auto()` (or `name: ClassVar[Cls] \u003d auto()`) — registers a\nvariant with no extra fields; the preferred form for simple enums.\n4. Bare `name: ClassVar[Cls]` — binds to a C++-registered entry of the\nsame name, or registers a blank Python entry if none exists.\n\nWithin one class body, bare `ClassVar` binders resolve first (annotation\norder), then sentinel assignments (class-body order); auto-ordinals\nfollow that combined order. Mixing all four forms on a single class is\nsupported.\n- **Auto-detected backend.** `Enum.__init_subclass__(type_key\u003d...)`\nroutes the subclass through `@c_class` if the type is already registered\nin the FFI type system, otherwise through `@py_class`. There is no\nseparate `py_enum`/`c_enum` opt-in.\n- **Integer literals are rejected** on the RHS. The auto-ordinal policy\nowns `value`, so `ok \u003d 0` and `entry(0)` would either duplicate or\nconflict with the auto-ordinal. `auto()` is the intended replacement.\n`entry(value\u003d...)` / `entry(name\u003d...)` raise `TypeError` at class-body\ntime.\n\n## New public interfaces\n\n### C++ headers\n\n- `include/tvm/ffi/enum.h` — `EnumObj` (`int64_t value`, `String name`,\nboth `def_ro`-reflected) and `Enum` (nullable `ObjectRef` wrapper),\nregistered under type key `ffi.Enum`. Plus two column-name constants\n`kEnumEntriesAttrName` (\u003d `\"__ffi_enum_entries__\"`) and\n`kEnumAttrsAttrName` (\u003d `\"__ffi_enum_attrs__\"`).\n- `include/tvm/ffi/reflection/enum_def.h` —\n`refl::EnumDef\u003cT\u003e(\"name\").set_attr(\"key\", value)...`. Each call\nallocates a fresh ordinal, constructs the instance, and writes it into\nthe per-class registry. Duplicate names for the same `T` raise\n`RuntimeError`. Exposes `.instance()` / `.ordinal()` for tests /\nadvanced callers.\n- `include/tvm/ffi/tvm_ffi.h` transitively includes both new headers.\n\n### Python surface (`tvm_ffi.dataclasses`)\n\n- `Enum` — base class, decorated\n`@dataclass_transform(field_specifiers\u003d(Field, field, entry, auto))` so\ntype checkers recognise `entry()` / `auto()` as dataclass-field\nspecifiers.\n- `entry(**kwargs)`, `auto()` — variant-declaration sentinels.\n- `EnumAttrMap` — view over the shared `__ffi_enum_attrs__` column;\n`__getitem__` / `__setitem__` / `__contains__` / `get(default\u003d...)`.\n- Per-subclass surface: `Cls.get(name)`, `Cls.entries()`,\n`Cls.def_attr(name, *, default\u003d...)`, and three live class-level\nproperties `Cls.by_name` (`Dict[str, Enum]`), `Cls.by_value`\n(`List[Enum]` indexed by ordinal), `Cls.attr_dict` (`Dict[str,\nList[Any]]`). The class-level properties are backed by an internal\n`_ClassProperty` descriptor so they work without a metaclass.\n\n## Other user-visible changes\n\n- **`TVMFFITypeRegisterAttr` rejects duplicate `(type_index, attr_name)`\nwrites.** Reverses a previously relaxed \"silent overwrite\" behaviour.\nThe enforced invariant is load-bearing for the register-once-then-mutate\nprotocol; the error message points callers at that protocol.\n- **Default repr for `EnumObj` subclasses** is `\u003ctype_key\u003e.\u003cname\u003e`\ninstead of the generic `type_key(field1\u003d..., field2\u003d...)` form. Rendered\nby `ReprPrinter` after the `__ffi_repr__` hook check, so explicit\noverrides still take precedence.\n- **Built-in sentinels `MISSING` / `KWARGS`** now render as `\u003cMISSING\u003e`\n/ `\u003cKWARGS\u003e` via pointer-identity dispatch, replacing the generic\n`ffi.Object` fallback.\n- **C++ test-support type `testing.TestEnumVariant`** (in\n`src/ffi/testing/testing.cc`) now extends `EnumObj` and registers\n`Alpha` / `Beta` entries with a `code` attribute via `refl::EnumDef`.\nThis is the canonical end-to-end demonstration of the builder and is\nexercised by the Python test suite.\n\n## Testing\n\n- `uv run pytest tests/python/test_dataclass_enum.py -q` — 38/38\npassing. Covers all four declaration forms, auto-ordinal assignment,\nfrozen-singleton identity, rejection of `entry(value\u003d...)` /\n`entry(name\u003d...)`, `get` / `entries` / `by_name` / `by_value` /\n`attr_dict`, `def_attr` round-trips through the unified column, direct\nTypeAttr verification, the C++-backed happy path against\n`testing.TestEnumVariant`, mixed C++/Python entry registration, and the\nrepr / sentinel behaviour.\n- `uv run pytest tests/python -q` — 2246 passed, 16 skipped, 3 xfailed.\nNo regressions.\n- `pre-commit run --all-files` — clean.\n\nC++ GoogleTest and Rust suites were not re-run; the enum builder is\nexercised end-to-end from the Python tests against\n`testing.TestEnumVariant`, and no Rust bindings were touched."
    },
    {
      "commit": "9c4f59878ba11950eaae22fa50d2d6a3c9322043",
      "tree": "bedcf24f5e99e62eb740b106fc7e5e9bd9340ddb",
      "parents": [
        "b8d810459a983f9c822a31b313348ea94c9af44c"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Apr 17 18:02:40 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 17 18:02:40 2026 -0700"
      },
      "message": "feat(dataclass): add asdict, astuple, and match_args support (#556)\n\n## Summary\n\nAdds three stdlib-parity features to `tvm_ffi.dataclasses`:\n\n1. **`asdict(obj, *, dict_factory\u003ddict)`** — recursively converts a\n`@py_class` / `@c_class` instance to a plain Python `dict`. FFI\ncontainers (`Array`, `List`) recurse into `list`; (`Map`, `Dict`)\nrecurse into `dict`, yielding JSON-ready output.\n2. **`astuple(obj, *, tuple_factory\u003dtuple)`** — the tuple analogue of\n`asdict`, with the same recursion rules.\n3. **`match_args: bool \u003d True`** parameter on `@py_class` and `@c_class`\n— sets `cls.__match_args__` to the tuple of positional `__init__` field\nnames (`init\u003dTrue and not kw_only`), enabling Python 3.10+ `match`\nstatements. Skipped when the class body already defines\n`__match_args__`.\n\nSemantics follow CPython\u0027s `dataclasses` module: `asdict`/`astuple`\nraise `TypeError` for types and non-dataclass values; kw-only fields\n(via `field(kw_only\u003dTrue)`, decorator-level `kw_only\u003dTrue`, or the\n`KW_ONLY` sentinel) are excluded from `__match_args__`.\n\n## Design notes\n\n- `_is_ffi_dataclass_instance` filters FFI container instances (`Array`,\n`List`, `Map`, `Dict`) from FFI dataclass instances — both share\n`__tvm_ffi_type_info__`, so the container isinstance-check runs first\nduring recursion.\n- `_set_match_args` walks the `TypeInfo.parent_type_info` chain in\nparent-first order, matching the order of the auto-generated `__init__`\nsignature.\n- Recursion uses an `_ATOMIC_TYPES` frozenset (mirroring stdlib\n`dataclasses._ATOMIC_TYPES`) for the fast path on immutable leaves.\n\n## Test plan\n\n- [x] `uv run pytest tests/python/` — 2184 passed, 38 skipped, 3 xfailed\n- [x] `pre-commit run --files \u003ctouched files\u003e` — all hooks pass (ruff,\nty, format)\n- [x] New coverage in `tests/python/test_dataclass_common.py`:\n- `TestAsdict` (15 tests): basic, nested, inheritance, FFI\nArray/List/Map/Dict recursion, `dict_factory`, result independence,\nerror paths\n- `TestAstuple` (10 tests): basic, nested, recursion, `tuple_factory`,\nerror paths\n- `TestMatchArgs` (11 tests): defaults, `init\u003dFalse`, kw_only (field /\ndecorator / `KW_ONLY` sentinel), inheritance order, `match_args\u003dFalse`\nopt-out, user-defined `__match_args__` override, c_class basic and\ninheritance"
    },
    {
      "commit": "b8d810459a983f9c822a31b313348ea94c9af44c",
      "tree": "fe23c337ea71eac51e9a4232096eb04cb3dc6861",
      "parents": [
        "02e9928a356c2d448e17d9fbdd37738cddceb0a1"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Apr 17 12:21:25 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 17 12:21:25 2026 -0700"
      },
      "message": "feat(dataclass): Introduce more utility methods in `tvm_ffi.dataclasses.*` (#555)\n\n## Summary\n\nThis PR introduces:\n- `tvm_ffi.dataclasses.fields` similar to\n[dataclasses.fields](https://docs.python.org/3/library/dataclasses.html#dataclasses.fields)\n- `tvm_ffi.dataclasses.replace` similar to\n[dataclasses.replace](https://docs.python.org/3/library/dataclasses.html#dataclasses.replace)\n- `tvm_ffi.dataclasses.is_dataclass` similar to\n[dataclasses.is_dataclass](https://docs.python.org/3/library/dataclasses.html#dataclasses.is_dataclass)\n- `tvm_ffi.Object.id_` similar to\n[id](https://docs.python.org/3/library/functions.html#id)\n- `tvm_ffi.Object.is_` similar to Python\u0027s `is` keyword\n\n## Test plan\n- [x] `uv run pytest tests/python` — 2148 passed, 38 skipped, 3 xfailed\n- [x] `pre-commit run --all-files` — 27 hooks passed\n- [x] New tests for every new attribute/flag and for `id_`/`is_` alias\nparity\n- [ ] CI lint + C++ unit tests + Rust tests"
    },
    {
      "commit": "02e9928a356c2d448e17d9fbdd37738cddceb0a1",
      "tree": "6ef2d510529888dda8f4040d79e762ccf2f60b7e",
      "parents": [
        "2f1a16a4d41fb05e0fc313ed20a3df35a9a9bca8"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 14 22:12:26 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 14 22:12:26 2026 -0700"
      },
      "message": "fix(py_class): remove __ffi_init_inplace__ to fix memory leak (#551)\n\n## Summary\n\n- **Fix memory leak** in `@py_class`: the custom `__new__` override\nallocated a spurious C++ object via `__ffi_new__` whenever a py_class\ninstance was returned from C++, which was then orphaned when\n`make_ret_object` overwrote `chandle` with the actual return value.\n- **Remove `__ffi_init_inplace__`** entirely — both the C++\n`MakeInitInplace` function, its registration, and the `kInitInplace`\nconstant.\n- **Unify `c_class` and `py_class`** auto-generated `__init__` to both\nuse `self.__init_handle_by_constructor__(ffi_init, *args)`, differing\nonly in guard logic: py_class uses a `chandle !\u003d 0` guard (no-op when\nalready allocated), c_class uses a `type_info` identity guard\n(`TypeError` from subclass).\n- **Remove the custom `__new__` override** — no more spurious allocation\non the `make_ret` path.\n- **Wrap user-defined `__init__`** on py_class with a `chandle \u003d\u003d 0`\nguard that pre-allocates via `__ffi_new__` before user code runs; use\n`functools.wraps` to preserve metadata.\n\n### Files changed\n\n| File | Change |\n|------|--------|\n| `python/tvm_ffi/_dunder.py` | Core redesign: removed `inplace` param,\nadded `py_class_mode`, removed `__new__` override, added user-init\nwrapping with `functools.wraps` |\n| `python/tvm_ffi/registry.py` | Removed `inplace\u003dFalse` kwarg from\n`_make_init` call |\n| `include/tvm/ffi/reflection/accessor.h` | Removed `kInitInplace`\nconstant |\n| `include/tvm/ffi/reflection/registry.h` | Updated comments (removed\n`__ffi_init_inplace__` references) |\n| `src/ffi/extra/dataclass.cc` | Removed `MakeInitInplace()`, its\nregistration, `EnsureTypeAttrColumn` call |\n| `python/tvm_ffi/dataclasses/py_class.py` | Updated comment |\n| `tests/python/test_dataclass_init.py` | Removed `TestInitInplace`\nclass (5 tests) |\n| `tests/python/test_dataclass_py_class.py` | Added 8 new tests in\n`TestPyClassNoLeak` |\n\n## Test plan\n\n- [x] All 27 pre-commit linters pass\n- [x] All 2103 Python tests pass (2095 existing + 8 new)\n- [x] All 349 C++ tests pass\n- [x] Memory leak validation: 20k construct+deepcopy cycles with no leak"
    },
    {
      "commit": "2f1a16a4d41fb05e0fc313ed20a3df35a9a9bca8",
      "tree": "fc7d74abdbfc25c1d038093cef96c48f5e13ee8a",
      "parents": [
        "528ce7cef74e3233d7082dbe017f44c7891fb372"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 14 14:59:28 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 14 14:59:28 2026 -0700"
      },
      "message": "feat(string): add String::Split, EscapedStringPy, and rename EscapeString (#550)\n\n## Summary\n\n- Rename `EscapeString` to `EscapeStringJSON` to clarify its\nJSON-specific escaping semantics (RFC 8259). A deprecated `EscapeString`\nalias is retained for backward compatibility.\n- Add `EscapedStringPy` for Python-style string escaping that handles\nANSI escape sequences, UTF-8 multibyte characters, and standard C escape\nsequences (`\\n`, `\\t`, `\\r`, `\\\\`, `\\\"`).\n- Add `String::Split(char delim)` utility method that returns\n`std::vector\u003cstd::string_view\u003e` segments.\n- Update all internal call sites (`function.h`, `registry.h`,\n`dataclass.cc`, `json_writer.cc`) to use the new `EscapeStringJSON`\nname.\n- `ReprPrinter` now uses `EscapedStringPy` instead of `EscapeStringJSON`\nfor proper Python-style `__repr__` output.\n\n## Motivation\n\nThe existing `EscapeString` function was JSON-specific but its name did\nnot convey this. This rename makes intent explicit. The new\n`EscapedStringPy` function supports Python-style repr output needed for\nerror messages and debugging. `String::Split` is a common utility needed\nacross the codebase.\n\n## Changes\n\n| File | Change |\n|------|--------|\n| `include/tvm/ffi/string.h` | Rename `EscapeString` -\u003e\n`EscapeStringJSON`, add deprecated alias, add `EscapedStringPy`, add\n`String::Split` |\n| `include/tvm/ffi/string.h` | Cast to `unsigned char` before\n`std::isdigit` to avoid UB; use `\\x1b` for ANSI escapes; validate UTF-8\ncontinuation bytes |\n| `include/tvm/ffi/function.h` | Update call site to `EscapeStringJSON`\n|\n| `include/tvm/ffi/reflection/registry.h` | Update call site to\n`EscapeStringJSON` |\n| `src/ffi/extra/dataclass.cc` | `ReprPrinter` uses `EscapedStringPy`\nfor Python-style repr output |\n| `src/ffi/extra/json_writer.cc` | Update call site to\n`EscapeStringJSON` |\n| `tests/cpp/test_string.cc` | Add 7 test cases for `Split`,\n`EscapeStringJSON`, `EscapedStringPy` (basic, control chars, ANSI,\nUTF-8, malformed UTF-8) |\n\n## Test plan\n\n- [x] All 47 C++ string tests pass\n- [x] `String::Split` tested with edge cases (empty, boundaries,\nconsecutive delimiters)\n- [x] `EscapeStringJSON` tested with special chars, backslash, quotes,\ncontrol chars\n- [x] `EscapedStringPy` tested: basic ASCII, control chars, ANSI\nsequences, valid UTF-8 (2/3/4-byte), malformed UTF-8\n- [x] Existing Python tests pass (deprecated alias preserves\ncompatibility)"
    },
    {
      "commit": "528ce7cef74e3233d7082dbe017f44c7891fb372",
      "tree": "048abf357ce742efbf20fd0d1fcfd2455748c75f",
      "parents": [
        "f26ff61eea2f7c3c9fe195ebb81873f30b33a81a"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 14 13:41:37 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 14 13:41:37 2026 -0700"
      },
      "message": "feat(dataclass): emit __ffi_init__ stubs, harden field registration, and support Python 3.14 (#549)\n\n## Summary\n\n- **Stub generation**: emit `__ffi_init__` stubs alongside `__init__`\nfor all reflected types, sourced from either TypeMethod (explicit\n`refl::init\u003c\u003e`) or synthesized from field metadata (auto-generated\ninit).\n- **Field registration hardening**: reject duplicate field names within\na type (C++ `ICHECK` + Python `assert`) and warn when child fields\nshadow ancestor fields, in both C++ (`object.cc`) and Cython\n(`type_info.pxi`).\n- **Python 3.14 compatibility (PEP 749)**: use `getattr(cls,\n\"__annotations__\", {})` on 3.14+ where annotations are lazily evaluated\nvia `__annotate__`, falling back to `cls.__dict__` on older versions.\n- **Additional fixes**: null-guard `DecRefObjectHandle`,\n`TVM_FFI_UNREACHABLE()` in `creator.h`, `signed char` cast fix for\nclang-tidy, MSVC `/bigobj`, allow non-callable type attrs in\n`_collect_py_methods`, consolidate test skip markers, update stubgen\ndocs."
    },
    {
      "commit": "f26ff61eea2f7c3c9fe195ebb81873f30b33a81a",
      "tree": "bef582087e8bc7a6717e3007bd0a376535c3617f",
      "parents": [
        "b7c30ea6e8264f8189c0ab94f2ebb04e955812ad"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 14 04:32:27 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 14 07:32:27 2026 -0400"
      },
      "message": "perf(container): use iterator lookup instead of exception handling in Map/Dict (#548)\n\n## Summary\n\n- Replace `try { n-\u003eat(k); } catch (...)` with `n-\u003efind(k)` + iterator\ncheck in `ffi.MapGetItemOrMissing` and `ffi.DictGetItemOrMissing`\n- Avoids the overhead of throwing and catching exceptions on every\nmissing-key lookup\n- No behavioral change: both paths return `GetMissingObject()` for\nabsent keys\n\nCloses #547\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python` -- 2088 passed, 38 skipped, 3\nxfailed (no new failures)\n- [x] Pre-commit hooks pass (clang-format, ASF header, file types, etc.)"
    },
    {
      "commit": "b7c30ea6e8264f8189c0ab94f2ebb04e955812ad",
      "tree": "b91a16097df67c5d052e46f1423044a79d42698a",
      "parents": [
        "e809f98099790f870184aa69537ffccce78b5a86"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 13 19:31:28 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 14 10:31:28 2026 +0800"
      },
      "message": "fix(init): register __ffi_init__ as TypeMethod and use MISSING sentinel (#546)\n\n## Summary\n\n- **C++ `def(init\u003c\u003e)`**: Register `__ffi_init__` as TypeMethod\n(preserving `type_schema` metadata for stub generation), then mirror to\nTypeAttrColumn for backward compatibility. Aligns\n`ObjectDef::def(init\u003c\u003e)` with `OverloadObjectDef::def(init\u003c\u003e)` which\nalready did this.\n- **Python `__ffi_init__` lookup**: Prefer TypeMethod over\nTypeAttrColumn when resolving `__ffi_init__` in `_install_init` and\n`_install_dataclass_dunders`.\n- **Python `_install_ffi_init_attr`**: New helper that installs\n`__ffi_init__` as an instance method with a type-owner guard, preventing\nsubclass misuse.\n- **MISSING sentinel**: Use `core.MISSING` (not a private `__SENTINEL`)\nfor default parameter values in auto-generated `__init__` signatures,\nand skip MISSING kwargs instead of forwarding them to C++.\n\n## Test plan\n\n- [x] 23 new regression tests added to `test_dataclass_init.py`\n  - TypeMethod registration for `def(init\u003c\u003e)` classes\n  - `__ffi_init__` as callable instance method\n  - Type-owner guard preventing subclass misuse\n  - `core.MISSING` sentinel for default parameters\n  - Dual TypeMethod/TypeAttrColumn availability\n- [x] All 2095 existing Python tests pass\n- [x] All pre-commit hooks pass (ruff, ty, clang-format)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 4.6 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "e809f98099790f870184aa69537ffccce78b5a86",
      "tree": "1ba66e15edbc155dcea6a52f200a9d3552c858ef",
      "parents": [
        "ef511d41402fed19927f663da90315b18db20cc8"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 13 10:56:54 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 13 10:56:54 2026 -0700"
      },
      "message": "feat(container): add structural `__eq__`/`__ne__`/`__hash__` to Array, List, Map, Dict (#545)\n\n## Summary\n\n- Add structural `__eq__`, `__ne__`, and `__hash__` methods to the four\ncontainer classes (`Array`, `List`, `Map`, `Dict`) in\n`python/tvm_ffi/container.py`\n- Delegates to existing `RecursiveEq` and `RecursiveHash` C++ FFI\nfunctions — the same infrastructure used by `_install_dataclass_dunders`\nin `_dunder.py` for `@c_class`/`@py_class`\n- Returns `NotImplemented` for unrelated types so Python\u0027s default\ncomparison fallback applies\n- `Shape`, `String`, and `Bytes` are unchanged (already inherit correct\nbehavior from `tuple`, `str`, `bytes`)\n\n## Breaking Change\n\nCode that relied on identity-based equality for containers will now see\nstructural equality instead. For example, `Array([1, 2]) \u003d\u003d Array([1,\n2])` now returns `True` (previously `False`). Two container objects with\nthe same contents now compare equal and produce the same hash.\n\n## Test Plan\n\n- [x] 17 new tests added in `tests/python/test_container.py` covering:\n  - Structural equality and inequality for all four container types\n  - Empty containers\n  - Nested containers (Array of Arrays)\n  - `NotImplemented` return for unrelated types (plain list, dict, str)\n  - Hash consistency (equal objects produce equal hashes)\n  - Usability as set members and dict keys\n- [x] Full Python test suite passes: 2072 passed, 38 skipped, 3 xfailed\n- [x] All pre-commit hooks pass (ruff, ty check, etc.)"
    },
    {
      "commit": "ef511d41402fed19927f663da90315b18db20cc8",
      "tree": "d895aa88c078041a702e6bc6baf2c7ef75c921cb",
      "parents": [
        "e10f635544b48ad52b13085369a55b38bc88b7be"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 13 01:00:22 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 13 01:00:22 2026 -0700"
      },
      "message": "feat(py_class): support `frozen\u003dTrue` for immutable instances (#542)\n\n## Summary\n\n- Add `frozen` parameter to `@py_class()` decorator and `field()`\nfunction, mirroring Python\u0027s `dataclasses.dataclass(frozen\u003dTrue)`\nsemantics.\n- **Class-level frozen**: `@py_class(frozen\u003dTrue)` installs\n`__setattr__`/`__delattr__` guards raising `FrozenInstanceError`. Frozen\nclasses auto-get `__hash__` (safely hashable).\n- **Field-level frozen**: `field(frozen\u003dTrue)` sets\n`TypeField.frozen\u003dTrue` (`fset\u003dNone`), independent of class-level\nfrozen.\n- `__replace__` (`copy.replace`) uses direct `FieldSetter` for\n`py_class` (bypasses both frozen mechanisms) while `c_class` respects\nC++ readonly fields via `object.__setattr__`.\n\n## Test plan\n\n- [x] 101 new tests in `tests/python/test_dataclass_frozen.py` covering:\n  - Class-level frozen basic behavior and error messages\n  - Field-level frozen (individual field override)\n  - Inheritance (frozen parent + mutable child, mixed)\n  - Interactions with `eq`, `hash`, `order`, `copy`, `replace`\n  - `object.__setattr__` escape hatch\n  - `FrozenInstanceError` is `AttributeError` subclass\n- [x] Full test suite: 2105 passed, 0 failed, 38 skipped, 3 xfailed"
    },
    {
      "commit": "e10f635544b48ad52b13085369a55b38bc88b7be",
      "tree": "fa875af0196406ef027d3d312f93a2b85432bfdf",
      "parents": [
        "cc1346a573d02a3836ad73d8e7850e14cb8d7eb0"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Apr 13 00:38:46 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 13 00:38:46 2026 -0700"
      },
      "message": "fix(c_class): restore `__init__` installation from `__ffi_init__` TypeAttrColumn (#543)\n\n## Summary\n\n- Fixes a regression from cc1346a5 (#541) where `register_object`\nstopped installing `__init__` from the C++ `__ffi_init__`\nTypeAttrColumn, causing segfaults when constructing objects like\n`IntPair` in `examples/python_packaging/`\n- Adds `_install_init(cls, type_info)` in `registry.py` that restores\nthe invariant: if `__ffi_init__` exists, install `__init__` via\n`_dunder._make_init`; if no reflection and no user `__init__`, install a\nTypeError guard instead of allowing segfaults\n- For `PyNativeObject` subclasses (e.g., `Shape`) that use `__new__`,\nthe helper is a no-op\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python/` -- 2004 passed, 38 skipped, 3\nxfailed\n- [x] `examples/python_packaging/run_example.py` constructs `IntPair`\ncorrectly\n- [x] Pre-commit hooks all pass"
    },
    {
      "commit": "cc1346a573d02a3836ad73d8e7850e14cb8d7eb0",
      "tree": "5bc2bbf5c967b0d203ffc3f17e9c12bbd03ddc87",
      "parents": [
        "be9a8274623252b48ac252961f5968255bf51114"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Apr 12 16:42:52 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 12 16:42:52 2026 -0700"
      },
      "message": "refactor(dataclass): consolidate dunder method installation into _dunder.py (#541)\n\n## Summary\n\n- Consolidate\n`__new__`/`__init__`/`__repr__`/eq/ne/ordering/hash/copy/deepcopy/replace\ninstallation for `@c_class` and `@py_class` into a single `_dunder.py`\nmodule with `_install_dataclass_dunders` as the entry point\n- Introduce `__ffi_new__` and `__ffi_init__`/`__ffi_init_inplace__` as\nuniversal `TypeAttrColumns`, replacing ad-hoc `__c_ffi_init__` renaming\nand `auto_init` metadata\n- Remove `init.h`; consolidate C++ registration into `dataclass.cc`;\neliminate `ffi.NewEmpty`, `ffi.MakeFFINew`, `ffi.RegisterAutoInit`\n- `py_class` uses `__ffi_init_inplace__` (object pre-allocated by\n`__new__`), `c_class` uses `__ffi_init__` (via\n`__init_handle_by_constructor__`)\n- Use factory pattern for copy/deepcopy/replace with install-time\nresolution\n- Add `KW_ONLY` regression tests"
    },
    {
      "commit": "be9a8274623252b48ac252961f5968255bf51114",
      "tree": "dacb106c135cae5d1a2dd0b9aaf441df640f33e3",
      "parents": [
        "aed51c05236be1835065c0ce4bd86dc54c3b934c"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Apr 12 13:05:04 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 12 13:05:04 2026 -0700"
      },
      "message": "fix(py_class): support `tvm_ffi.dtype` and `tvm_ffi.Device` as field type annotations (#540)\n\n## Summary\n\n- `TypeSchema.from_annotation()` in the Cython layer only recognized the\nC-level `DataType`/`Device` cdef classes for dtype/device annotations\n(`annotation is DataType`). The public Python wrapper classes —\n`tvm_ffi.dtype` (`class dtype(str)` in `_dtype.py`) and `tvm_ffi.Device`\n— are distinct types, so using them as `@py_class` field type\nannotations raised `TypeError: Cannot convert \u003cclass \u0027...\u0027\u003e to\nTypeSchema`.\n- The fix extends the identity checks to also match the Python wrapper\nclasses via the existing `_CLASS_DTYPE` / `_CLASS_DEVICE` module-level\nsentinels.\n- Added 6 regression tests covering dtype fields, Device fields,\ncombined usage, setter mutation, and `Optional` variants.\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python/test_dataclass_py_class.py` — all\n342 tests pass (including 6 new `TestDtypeDeviceFields` tests)\n- [ ] CI: lint, C++ tests, full Python test suite, Rust tests\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "aed51c05236be1835065c0ce4bd86dc54c3b934c",
      "tree": "fc101cafbba4a4d1bee64fd71692b66842e04713",
      "parents": [
        "2b59825e87a70dac521490802306e461024cc4d1"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Apr 12 13:04:48 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 12 13:04:48 2026 -0700"
      },
      "message": "fix(py_class): propagate parent total_size through empty intermediate classes (#539)\n\n## Summary\n\n- **Bug**: In Python-defined type hierarchies, when an intermediate\nparent class\nhad no own fields (e.g., `GrandParent(x, y) -\u003e Parent(pass) -\u003e Child(a,\nb)`),\n`TypeInfo.total_size` fell back to `sizeof(TVMFFIObject)` (~24 bytes)\nfor the\nempty parent, ignoring inherited fields. This caused child field offsets\nto\noverlap with grandparent field offsets, leading to silent data\ncorruption on\n  read/write.\n- **Fix**: Replace the `sizeof(TVMFFIObject)` floor with\n`self.parent_type_info.total_size` in `TypeInfo.total_size`, ensuring\ninherited\nfield space propagates correctly through arbitrarily deep empty parents.\nAdded a\nguard that `parent_type_info` must be present and an assertion that the\nbase size\n  is at least `sizeof(TVMFFIObject)`.\n- **Tests**: Added 6 regression tests in `TestFieldInheritance` covering\noffset\ncorrectness, total_size propagation, non-overlapping child offsets,\ntwo-level\nempty intermediate parents, mutation aliasing, and the `@py_class`\ndecorator path.\n\n## Architecture\n\n- **Changed file**: `python/tvm_ffi/cython/type_info.pxi` —\n`TypeInfo.total_size`\n  property body (6 lines replaced with 6 lines; decorator unchanged).\n- **Root cause**: The old code initialized `end \u003d sizeof(TVMFFIObject)`\nand only\niterated over `self.fields` (the type\u0027s own fields). An empty\nintermediate class\nhas no own fields, so it returned a total_size equal to just the object\nheader,\n  erasing all inherited field space.\n- **Fix mechanism**: `end \u003d self.parent_type_info.total_size` inherits\nthe parent\u0027s\nfull layout (including transitively inherited fields), then `max(end,\nf.offset + f.size)`\n  extends it for any own fields.\n\n## Behavioral Changes\n\n- Before: `Child.a` at offset 24 overlapping `GrandParent.x` at offset\n24 when\n  `Parent` had no own fields. Reading `obj.x` returned `obj.a`\u0027s value.\n- After: `Child.a` starts at or after `Parent.total_size` (which equals\n  `GrandParent.total_size`), so no field overlap occurs.\n\n## Test Plan\n\n- [x] `uv run pytest -vvs\ntests/python/test_dataclass_py_class.py::TestFieldInheritance` -- all\ntests pass (8 existing + 6 new)\n- [x] All pre-commit hooks pass"
    },
    {
      "commit": "2b59825e87a70dac521490802306e461024cc4d1",
      "tree": "337bb409696b1c591f6cc8c948523a925e56987a",
      "parents": [
        "f41dbfd648f5f2be82986aebcd3201f10c1d2974"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Apr 10 11:26:30 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 10 11:26:30 2026 -0700"
      },
      "message": "fix(py_class): support `super().__init__()` in `init\u003dFalse` subclasses (#532)\n\n## Summary\n\n- Fix segfault when `@py_class(init\u003dFalse)` subclasses use\n`super().__init__()` followed by field assignment\n- Add `ffi.NewEmpty` C++ function to allocate zero-initialized objects\nby type index\n- Detect super-init-from-subclass pattern in `_make_init()` and\npre-allocate instead of dispatching to `__ffi_init__`\n\n## Motivation\n\nThe common Python pattern of defining a custom `__init__` that calls\n`super().__init__()` then sets fields crashes when used with\n`@py_class(init\u003dFalse)`:\n\n```python\n@py_class(init\u003dFalse)\nclass PointerType(Node):\n    element_type: Object\n\n    def __init__(self, element_type):\n        super().__init__()       # parent\u0027s auto-init dispatches to child\u0027s C++ ctor → crash\n        self.element_type \u003d element_type\n```\n\nThe parent\u0027s auto-generated `__init__` forwards to `__ffi_init__` using\nthe child type\u0027s C++ constructor, which expects field arguments that\nwere not provided.\n\n## Design\n\n**C++ side** (`src/ffi/extra/dataclass.cc`): Register\n`ffi.NewEmpty(type_index) -\u003e ObjectRef` that allocates a\nzero-initialized object via `CreateEmptyObject`. The calloc\u0027d state is\nvalid: `None` for `Any`/`ObjectRef` fields, `0` for scalars.\n\n**Python side** (`python/tvm_ffi/registry.py`):\n- `_ffi_alloc_empty(obj)`: Calls `ffi.NewEmpty` to allocate an empty FFI\nobject for `type(obj)` and moves the handle into `obj`. No-op if already\nallocated.\n- `_is_super_init_from_subclass(self)`: Compares\n`type(self).__tvm_ffi_type_info__` identity against the declaring\nclass\u0027s `type_info`. Returns `True` only for registered `@py_class`\nsubclasses — undecorated subclasses inherit the parent\u0027s `type_info` so\nthe identity check correctly filters them out.\n- Both `_make_init` code paths (with/without `__post_init__`) intercept\nthe no-args super-init-from-subclass call and allocate an empty object\ninstead of dispatching to `__ffi_init__`.\n\n## Test plan\n\n- [x] `uv run pytest -vvs\ntests/python/test_dataclass_py_class.py::TestSuperInitPattern` — 12\ntests pass\n- [x] `uv run pytest -vvs tests/python/` — 1970 passed, 38 skipped, 3\nxfailed, 0 failures\n\nTests cover: basic super-init, deep hierarchy\n(Node→BaseType→PointerType), calloc defaults, intermediate custom/auto\ninits, normal init unaffected, non-py_class subclass error handling,\nisinstance checks, field overwrite, copy/deepcopy, and\ndirect-from-Object inheritance."
    },
    {
      "commit": "f41dbfd648f5f2be82986aebcd3201f10c1d2974",
      "tree": "b81984d4c1d789eefda858c8f7c444e6d8254c8f",
      "parents": [
        "059f8af3436b4b1fc629ba6d2c87f6be72513aeb"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Apr 10 08:41:17 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 10 08:41:17 2026 -0700"
      },
      "message": "feat(c_class): warn when reflected fields lack Python type annotations (#531)\n\n## Summary\n\n- When a `@c_class`-decorated class has C++-reflected fields without\ncorresponding Python type annotations, the decorator now emits a\n`UserWarning` at class-definition time listing the missing names.\n- This gives library authors an early, actionable signal that IDE\nsupport (autocompletion, type checking, hover docs) is degraded for\nthose fields.\n- The warning is non-breaking: filterable via the standard `warnings`\nmodule and does not alter runtime semantics.\n\n## Changes\n\n- **`python/tvm_ffi/registry.py`** — new\n`_warn_missing_field_annotations` helper\n- **`python/tvm_ffi/dataclasses/c_class.py`** — call the helper after\n`register_object()` succeeds\n- **`tests/python/test_dataclass_c_class.py`** — 5 new test cases\n(all/no/partial annotations, zero fields, derived class)\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python/test_dataclass_c_class.py` passes\nlocally\n- [ ] CI green on all platforms"
    },
    {
      "commit": "059f8af3436b4b1fc629ba6d2c87f6be72513aeb",
      "tree": "cfa27753b9153f5207ea483927321ab40c1be5a5",
      "parents": [
        "3d33014ba11fb5556fcd10a9cc11a540dd799443"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Apr 10 06:03:30 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 10 09:03:30 2026 -0400"
      },
      "message": "fix(cython): Segfault in free-threaded Py_DecRef Cleanup (#529)\n\nFree-threaded CPython still requires an attached PyThreadState before\nusing the Python C API. tvm-ffi skipped that setup under\nPy_GIL_DISABLED, so native cleanup paths could call Py_DecRef without\nthread state and crash.\n\nAlways attach thread state around native decref paths, and add a\nfree-threaded regression test that drops the last ref from a\ndetached-thread-state region. The test is skipped on non-free- threaded\nbuilds and runs in the existing 3.14t CI job."
    },
    {
      "commit": "3d33014ba11fb5556fcd10a9cc11a540dd799443",
      "tree": "479b709360280b0af37b67a1d93043c0b6239dbc",
      "parents": [
        "1a305b63b17f41695c97d379dff96c6169cdb209"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Wed Apr 08 00:23:40 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 08 15:23:40 2026 +0800"
      },
      "message": "build(deps): replace cmake version exclusion with uv exclude-newer (#526)\n\nRemove the `cmake\\!\u003d4.3.1` version pin from dev dependencies and instead\nadd a `[tool.uv] exclude-newer \u003d \"14 days\"` setting. This prevents\ninstalling any package released within the last 14 days, which is a more\ngeneral and maintainable approach to avoiding freshly-released broken\npackages across the entire dependency tree.\n\n- Architecture: No changes.\n- Public Interfaces: No changes.\n- UI/UX: No changes.\n- Behavioral Changes: `uv` will now exclude packages newer than 14 days\nfor all resolution, not just cmake. The cmake-specific version exclusion\nis removed.\n- Docs: No changes needed (build config only).\n- Tests: No changes needed (config-only change).\n- Untested Edge Cases: The `exclude-newer` directive is relative (\"14\ndays\"), so resolution results will vary by the date `uv` is invoked. CI\nreproducibility depends on lockfile presence."
    },
    {
      "commit": "1a305b63b17f41695c97d379dff96c6169cdb209",
      "tree": "ce838318369bbc7409a8cb0a0940b499fd5e6958",
      "parents": [
        "d964f294229150b425a054b5efada0602acb1cbf"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Wed Apr 08 00:01:01 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 08 15:01:01 2026 +0800"
      },
      "message": "Revert \"build(deps): replace cmake version exclusion with uv exclude-newer\" (#525)\n\nReverts apache/tvm-ffi#524\n\nMade a mistake that I incorrectly pushed a staging branch to the\nprevious branch"
    },
    {
      "commit": "d964f294229150b425a054b5efada0602acb1cbf",
      "tree": "eeb8a512f7cab683eeccf37835976f68663c0ee2",
      "parents": [
        "bd87b3b04c0b9f7ff9fc73842507990ded91fae6"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 07 22:29:36 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 07 22:29:36 2026 -0700"
      },
      "message": "build(deps): replace cmake version exclusion with uv exclude-newer (#524)\n\n## Summary\n\n- Remove the `cmake!\u003d4.3.1` version pin from dev dependencies, which was\na temporary workaround for a specific broken cmake release.\n- Add `[tool.uv] exclude-newer \u003d \"30 days\"` to prevent installing any\npackage released within the last 30 days, providing a more general and\nmaintainable guard against freshly-released broken packages across the\nentire dependency tree."
    },
    {
      "commit": "bd87b3b04c0b9f7ff9fc73842507990ded91fae6",
      "tree": "ce838318369bbc7409a8cb0a0940b499fd5e6958",
      "parents": [
        "8d1ba380c613b30b5910340ec009837729131db1"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Apr 07 12:50:41 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 07 12:50:41 2026 -0700"
      },
      "message": "chore(release): Version bump after release v0.1.10 (#522)"
    },
    {
      "commit": "8d1ba380c613b30b5910340ec009837729131db1",
      "tree": "65b23a91b22cad7eb6e69f311c4db64ef01bc672",
      "parents": [
        "3539d7077620dbade194bd231091cd4029924b83"
      ],
      "author": {
        "name": "Kathryn (Jinqi) Chen",
        "email": "65606304+Kathryn-cat@users.noreply.github.com",
        "time": "Thu Apr 02 11:28:42 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 02 11:28:42 2026 -0700"
      },
      "message": "[fix] Move container stream scanning from Cython to C++ for efficiency (#521)\n\nWhen a packed FFI function receives containers (Array, List, Map, Dict)\ncontaining tensors, we scan for the first non-CPU tensor to capture\nstream context. Previously this scanning was done in Cython via repeated\npacked-function calls (size, getitem, iterator create/advance per\nelement). This PR registers a single C++ function\nffi.ContainerFindFirstNonCPUDevice that does the recursive scan\nnatively."
    },
    {
      "commit": "3539d7077620dbade194bd231091cd4029924b83",
      "tree": "a59c3a16c6dc7f569800535864c8a386793d5cfa",
      "parents": [
        "1fed0ae0421e614d45662e8ee6bcae353d3ab2ea"
      ],
      "author": {
        "name": "Kathryn (Jinqi) Chen",
        "email": "65606304+Kathryn-cat@users.noreply.github.com",
        "time": "Thu Apr 02 00:18:14 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 02 00:18:14 2026 -0700"
      },
      "message": "[FEAT] Recursive DLPack container conversion for auto torch.Tensor return (#517)\n\n### Problem\n\nWhen a packed FFI function receives `torch.Tensor` inputs, the return\nvalue is automatically converted back to `torch.Tensor` via DLPack — but\nonly for bare ffi.Tensor returns. When the return is a container (Array,\nList, Map, Dict) containing tensors, the tensors inside remain as\nffi.Tensor, requiring manual per-element conversion.\n\n### Solution\n\nWe perform a lazy conversion of each element in the container from\nffi::Tensor to torch::Tensor when they\u0027re retrieved. A lazy conversion\nensures both semantic correctness of containers and reduce runtime\noverhead compared with eager conversion.\n\n### Stream Propagation\n| Container | Element | Stream set? | How |\n| :--- | :--- | :--- | :--- |\n| list/tuple | torch.Tensor | Yes | ConstructorCall → each element hits\nDLPackExchangeAPI_ setter |\n| list/tuple | ffi.Tensor | No | ConstructorCall → each element hits\nTensor_ setter (no stream) |\n| dict | torch.Tensor (values) | Yes | Same as above via ConstructorCall\n|\n| dict | ffi.Tensor (values) | No | Same as above |\n| ffi.Array/ffi.List (tagged) | ffi.Tensor | Yes | ContainerObject_\nsetter → _scan_seq_for_stream |\n| ffi.Map/ffi.Dict (tagged) | ffi.Tensor | Yes | ContainerObject_ setter\n→ _scan_map_for_stream |\n| ffi.Array/ffi.List (untagged) | ffi.Tensor | No | Object_ setter\n(pass-through) |\n| ffi.Map/ffi.Dict (untagged) | ffi.Tensor | No | Object_ setter\n(pass-through) |"
    },
    {
      "commit": "1fed0ae0421e614d45662e8ee6bcae353d3ab2ea",
      "tree": "f772f6b97252a8855f6137d48252630f84a95f60",
      "parents": [
        "61f90ebed458da702b4e89e260bf9f9568955fab"
      ],
      "author": {
        "name": "Akaash Parthasarathy",
        "email": "43900735+akaashrp@users.noreply.github.com",
        "time": "Wed Apr 01 15:29:51 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 01 12:29:51 2026 -0700"
      },
      "message": "[FFI][Reflection] Lazily resolve KWARGS sentinel in auto-init (#519)\n\nThis PR intends to avoid the eager lookup of `ffi.GetKwargsObject`\nduring `MakeInit` construction. Instead, it resolves and caches the\nKWARGS sentinel via a function-local static (`GetKwargsSentinel`) when\n`__ffi_init__` is invoked. This removes static-init order dependence\nbetween reflection auto-init registration and global function\nregistration, preventing `Function ffi.GetKwargsObject not found`\nfailures."
    },
    {
      "commit": "61f90ebed458da702b4e89e260bf9f9568955fab",
      "tree": "e62311cd0d32af03ae84c1dccf53c7f908d1c231",
      "parents": [
        "1da563747d5552a4d8f6a9f2bac063426d9c1ba5"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Mar 31 10:54:02 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Mar 31 13:54:02 2026 -0400"
      },
      "message": "fix(ci): pin pypa/gh-action-pypi-publish to SHA for Apache allowlist (#518)\n\n## Summary\n\n- Pin `pypa/gh-action-pypi-publish` from `@release/v1` (branch ref) to\n`@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e` (v1.13.0 SHA) in all three\npublish workflows\n- Fixes `startup_failure` in the \"Publish wheel\" workflow ([failed\nrun](https://github.com/apache/tvm-ffi/actions/runs/23773754182)) caused\nby Apache\u0027s org-level action allowlist requiring SHA-pinned third-party\nactions\n- Same class of fix as d8bd189 (#507), which pinned `astral-sh/setup-uv`\nand `pypa/cibuildwheel`\n\n### Files changed\n\n- `.github/workflows/publish_wheel.yml`\n- `.github/workflows/publish_orcjit_wheel.yml`\n- `.github/workflows/torch_c_dlpack.yml`\n\n## Test plan\n\n- [ ] Verify the \"Publish wheel\" workflow no longer fails with\n`startup_failure`\n- [ ] Confirm all three publish workflows pass CI"
    },
    {
      "commit": "1da563747d5552a4d8f6a9f2bac063426d9c1ba5",
      "tree": "60a41783188b6c0b7f693788a4be6bbcd08620d6",
      "parents": [
        "dbf64e88c5f171da493ea887acc7ae5887101676"
      ],
      "author": {
        "name": "Yaoyao Ding",
        "email": "dingyaoyao.cs@gmail.com",
        "time": "Fri Mar 27 10:19:23 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Mar 27 22:19:23 2026 +0800"
      },
      "message": "[OrcJIT] Add LLVM ORC JIT v2 dynamic object loader addon (#254)\n\nThis PR introduces a new addon package `tvm-ffi-orcjit` that enables\ndynamic loading of TVM-FFI exported object files (.o) at runtime using\nLLVM\u0027s ORC JIT v2 engine.\n\nThe addon provides a Python API for loading compiled object files, load\nthe tvm-ffi functions defined in the object files.\n\nThe API is organized around three main concepts:\n- **ExecutionSession**: A JIT compilation context that manages the\nlifetime of dynamic libraries.\n- **DynamicLibrary**: Represents a shared library that links multiple\nobject files.\n- **Object Files**: Compiled `.o` files containing TVM-FFI exported\nfunctions.\n\n## Usage Example\n\n```python\nfrom tvm_ffi_orcjit import create_session\n\n# Create an execution session (JIT compilation context)\nsession \u003d create_session()\n\n# Load an object file into the session, returns a DynamicLibrary handle\ndylib \u003d session.load(\"example.o\")\n\n# Get and call a function from the loaded object file\nadd_func \u003d dylib.get_function(\"simple_add\")\nresult \u003d add_func(1, 2)\nprint(f\"Result: {result}\")  # Output: Result: 3\n```\n\nFor incremental loading, you can add multiple object files to the same\nsession:\n\n```python\nsession \u003d create_session()\n\n# Load first object file\ndylib \u003d session.load(\"math_ops.o\")\nadd \u003d dylib.get_function(\"simple_add\")\n\n# Incrementally load more object files into the same library\ndylib.load(\"string_ops.o\")\n\n# Now both functions are accessible from the same library\nconcat \u003d dylib.get_function(\"string_concat\")\n```\n\nSee the test for more example.\n\n## TODO\n\n- Support Windows platform (currently Linux and macOS only)\n- Customize memory allocation for dynamic libraries (allow user-provided\nallocators)\n\n---------\n\nCo-authored-by: Yaxing Cai \u003ccaiyaxing666@gmail.com\u003e"
    },
    {
      "commit": "dbf64e88c5f171da493ea887acc7ae5887101676",
      "tree": "2216607a5e60f5de04c63b07edbdf8a4e8d301a9",
      "parents": [
        "63224e3f1e464cc62307223787926a48fc8df8c0"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Thu Mar 26 20:47:21 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Mar 26 20:47:21 2026 -0400"
      },
      "message": "[FEAT] Add map_dataclass_to_tuple to make_kwargs_wrapper (#515)\n\nAdd a `map_dataclass_to_tuple` parameter to `make_kwargs_wrapper` and\n`make_kwargs_wrapper_from_signature` that accepts a list of argument\nnames whose dataclass values should be converted to tuples (via\n`dataclasses.astuple`) before being passed to the target function.\n\nThis enables callers to pass dataclass instances to FFI functions that\nexpect flattened tuple arguments, matching the calling convention. The\nconversion is injected into the generated wrapper code, so there is no\noverhead when the feature is not used."
    },
    {
      "commit": "63224e3f1e464cc62307223787926a48fc8df8c0",
      "tree": "0a92bf8e3be43fa587c9243a46436e6e102519ae",
      "parents": [
        "41d38fa32f361fd219463455e5ef061e43a85945"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Mar 24 12:31:44 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Mar 24 12:31:44 2026 -0700"
      },
      "message": "fix(build): resolve type ambiguity and macro redefinition in unity builds (#512)\n\n## Summary\n- **`src/ffi/object.cc`**: Replace `using namespace tvm::ffi;` with a\nnamespace alias (`namespace ffi \u003d ::tvm::ffi;`) and fully qualify all\ntype names in the static init block. This prevents ambiguous type\nreferences (e.g. `Object` matching both `tvm::ffi::Object` and\n`tvm::runtime::Object`) in downstream wasm projects that include tvm-ffi\nsources in a unity build.\n- **`src/ffi/testing/testing.cc`**: Remove the `#define\nTVM_FFI_DLL_EXPORT_INCLUDE_METADATA 1` from the source file to avoid\nmacro redefinition warnings in unity builds where the macro is already\nset by the build system.\n- **`CMakeLists.txt`**: Add `target_compile_definitions(tvm_ffi_testing\nPRIVATE TVM_FFI_DLL_EXPORT_INCLUDE_METADATA\u003d1)` so the define is\nprovided via the build system instead of hardcoded in source.\n\n## Test plan\n- [ ] Verify existing C++ tests pass (`ctest` in CI)\n- [ ] Verify downstream wasm unity builds compile without ambiguity\nerrors or macro redefinition warnings"
    },
    {
      "commit": "41d38fa32f361fd219463455e5ef061e43a85945",
      "tree": "d8031fd76b13228a3838c199b589fb04e65acccc",
      "parents": [
        "d153a2c9407ee04ec3dc1ccbdf6a0664854337b7"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Mar 23 07:38:54 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 23 07:38:54 2026 -0700"
      },
      "message": "refactor(python)!: rename `structure\u003d` to `structural_eq\u003d` (#509)\n\n## Summary\n\n- Rename the `structure\u003d` parameter to `structural_eq\u003d` in `@py_class()`\nand `field()` to better convey that the parameter controls structural\nequality/hashing behavior\n- Update Cython layer (`type_info.pxi`) to read the new attribute name\n- Update all tests and documentation to use the new parameter name\n\n## Breaking Change\n\nThe `structure\u003d` parameter on `@py_class()` and `field()` has been\nrenamed to `structural_eq\u003d`.\n\n**Migration**: replace all occurrences of `structure\u003d` with\n`structural_eq\u003d` in your `@py_class()` and `field()` calls:\n\n```python\n# Before\n@py_class(structure\u003d\"tree\")\nclass MyNode(Object):\n    span: Object \u003d field(structure\u003d\"ignore\")\n\n# After\n@py_class(structural_eq\u003d\"tree\")\nclass MyNode(Object):\n    span: Object \u003d field(structural_eq\u003d\"ignore\")\n```\n\n## Test plan\n\n- [x] `uv pip install --force-reinstall --verbose -e .` (full C++\nrebuild required)\n- [x] `uv run pytest -vvs tests/python/test_structural_py_class.py`\n- [ ] Verify all pre-commit hooks pass (confirmed locally: all passed)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "d153a2c9407ee04ec3dc1ccbdf6a0664854337b7",
      "tree": "d409562b5907742b6ba8061e41ede9923552c233",
      "parents": [
        "d8bd1890ba407181f18284a6714d1c8cca57dd52"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Mar 22 14:24:35 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Mar 22 14:24:35 2026 -0700"
      },
      "message": "feat(python): auto-register __ffi_* dunder methods in @py_class as TypeMethod (#508)\n\n## Summary\n\n- Extend `@py_class` to detect and register recognized FFI dunder\nmethods (`__ffi_repr__`, `__ffi_eq__`, `__s_equal__`, etc.) defined on\nPython dataclasses, making them callable from C++ and other FFI\nlanguages\n- `_FFI_RECOGNIZED_METHODS` allowlist in `py_class.py` gates which\ndunders are collected; `_collect_py_methods()` scans class dict and\n`TypeInfo._register_py_methods()` registers via the C API\n(`TVMFFITypeRegisterMethod` + `TVMFFITypeRegisterAttr`)\n- No C++ changes — `dataclass.cc` is unmodified from upstream\n\n## Changes since v1\n\n- Rebased onto upstream/main (`d8bd1890`) which adds structural\nequality/hashing support (#507)\n- Resolved merge conflicts: preserved `structure_kind` /\n`STRUCTURE_KIND_MAP` from upstream\n- Applied Gemini Code Assist review feedback:\n- **HIGH**: Fixed `func_any` memory leak in `_register_py_methods` by\nadding `TVMFFIObjectDecRef` in a `try/finally` block\n- **MEDIUM**: Changed `_collect_py_methods` to iterate\n`cls.__dict__.items()` instead of `list(cls.__dict__)` + second lookup\n\n## Test plan\n\n- [x] 12 new dedicated tests covering allowlist filtering, registration,\nround-trip dispatch (repr, eq, compare, hash)\n- [x] All 693 tests pass (including structural equality tests that now\nwork with the `structure_kind` base from #507)\n- [ ] CI: lint, C++ tests, Python tests, Rust tests\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "d8bd1890ba407181f18284a6714d1c8cca57dd52",
      "tree": "06f4644236cbb2a581425dede5c2f2bd87aa6ecf",
      "parents": [
        "bc8f30d77b49f5386bc2d43a0cf4ec053fa0e05a"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Mar 22 10:59:29 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Mar 22 10:59:29 2026 -0700"
      },
      "message": "feat(python): add structural equality/hashing support to `py_class` and `field` (#507)\n\n## Summary\n\n- Add `structure\u003d` parameter to `@py_class()` and `field()` controlling\nstructural equality/hashing behavior. Class-level values: `\"var\"`,\n`\"tree\"`, `\"const-tree\"`, `\"dag\"`. Field-level values: `\"ignore\"`,\n`\"def\"`. Dispatched via Cython-accelerated `_ffi_seq_hash_kind` and\n`_ffi_field_info_seq_hash` attributes, mapping to C++\n`TVMFFISEqHashKind` and `SEqHashIgnore`/`SEqHashDef` field flags.\n- Expand `py_class` test coverage with 349 tests ported from mlc-python\n(field parsing, defaults, inheritance, JSON serialization, nested\nstructures, edge cases).\n- Add `docs/concepts/structural_eq_hash.rst` documenting the structural\nequality/hashing design.\n- Pin `astral-sh/setup-uv` to v7.3.1 and `pypa/cibuildwheel` to v3.3.1\n(Apache-approved SHAs), fixing CI permission failures in\nhttps://github.com/apache/tvm-ffi/actions/runs/23389552989.\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python/test_dataclass_py_class.py\ntests/python/test_structural_py_class.py` — 349 passed\n- [x] All pre-commit hooks pass"
    },
    {
      "commit": "bc8f30d77b49f5386bc2d43a0cf4ec053fa0e05a",
      "tree": "137326aa1a6083eb7076b2f2d83996cc14a08872",
      "parents": [
        "6a61156cb6780101d633a72a5151b65602f8b7e2"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Mar 21 14:50:26 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Mar 21 14:50:26 2026 -0700"
      },
      "message": "feat(python): add `@py_class` decorator for Python-defined FFI dataclasses (#506)\n\n## Summary\n\nAdd `@py_class`, a new decorator that lets users define TVM FFI Object\ntypes entirely in Python with dataclass-style field annotations. This\ncomplements `@c_class` (which wraps C++-backed types) by enabling\npure-Python FFI types that participate in the same object system -- type\nregistry, reference counting, cross-language serialization, and\npacked-function interop.\n\n### Motivation\n\nCurrently, defining a new FFI-visible type requires either writing C++\n(`ObjectDef\u003cT\u003e`) or using `@c_class` which expects C++ reflection\nmetadata. `@py_class` removes the C++ requirement entirely: annotate\nfields with Python types, and the decorator handles type-index\nallocation, field registration, and dunder generation.\n\n### Usage\n\n```python\nfrom tvm_ffi.dataclasses import py_class, field\nfrom tvm_ffi import Object\n\n@py_class\nclass Point(Object):\n    x: float\n    y: float\n\n@py_class(\"my.namespace.Line\", eq\u003dTrue)\nclass Line(Object):\n    start: Point\n    end: Point\n    label: str \u003d \"default\"\n```\n\n## Architecture\n\nRegistration is split into two phases to handle forward and mutual\nreferences:\n\n- **Phase 1** (`_phase1_register_type`): Allocates a C-level type index\nand inserts the class into the global type registry. Runs eagerly so\nthat self-referential and mutually-referential annotations can be\nresolved.\n- **Phase 2** (`_phase2_register_fields`): Resolves string annotations\nvia `typing.get_type_hints`, converts them to `TypeSchema`/`Field`\nobjects, validates field ordering, registers fields with the Cython\nlayer, and installs `__init__`/`__repr__`/`__eq__`/etc.\n\nWhen `get_type_hints` raises `NameError` (forward reference not yet\ndefined), the class is deferred to a pending list and retried after each\nsuccessful phase-2. A temporary `__init__` triggers lazy completion on\nfirst instantiation. Failed phase-2 rolls back phase-1 so the type key\ncan be reused.\n\n## Public Interfaces\n\n| Symbol | Location | Description |\n|--------|----------|-------------|\n| `@py_class` | `tvm_ffi.dataclasses.py_class` | Main decorator (bare,\nstring-key, and kwarg calling conventions) |\n| Parameters | `type_key`, `init`, `repr`, `eq`, `order`, `unsafe_hash`,\n`kw_only`, `slots` | Mirrors `dataclasses.dataclass` semantics |\n\n## Test Plan\n\n- [x] 246 tests across 47 test classes\n(`tests/python/test_dataclass_py_class.py`, 3533 lines)\n- [x] Coverage includes: basic registration, field parsing,\ndefaults/factories, kw_only, ClassVar, init generation, post_init, repr,\nequality, ordering, hashing, copy/deepcopy, single/multi-level\ninheritance, forward/mutual references, dunder preservation,\nregistration rollback, type conversion errors, getter/setter corner\ncases, memory lifetime, bool alignment, optional fields, Any fields, FFI\nglobal function interop\n- [x] All 1817 Python tests pass (25 skipped, 3 xfailed) -- no\nregressions\n- [x] All pre-commit hooks pass\n\n### Untested Edge Cases\n\n- Thread safety of the pending-class flush mechanism\n- Interaction with `importlib.reload()` on modules containing\n`@py_class`-decorated types\n- Deeply nested generic type annotations (e.g. `List[Optional[Map[str,\nArray[int]]]]`)"
    },
    {
      "commit": "6a61156cb6780101d633a72a5151b65602f8b7e2",
      "tree": "b92b974ce2d55e6000f0d45883578e40a0deaf4a",
      "parents": [
        "1968f9dc0527c93db348bcc3fb3238330c141f8d"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Mar 20 12:05:12 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Mar 20 12:05:12 2026 -0700"
      },
      "message": "feat(python): add field registration, _register_py_class, and Field descriptor (#505)\n\n## Summary\n\n- Implement the Python-side type registration pipeline for\n`@py_class`-decorated classes: allocates dynamic type indices, computes\nnative field layouts, registers getters/setters with type-converting\ncallbacks, and wires up `__ffi_new__`/`__ffi_init__` for automatic\nconstruction.\n- Add `Field` descriptor and `field()` factory function mirroring stdlib\n`dataclasses.field()` API.\n- Fix dunder family-skip logic so user-defined `__eq__` suppresses\ngenerated `__ne__` (and vice versa), same for ordering operators.\n\n## Architecture\n\nThree-layer implementation:\n- **Cython `object.pxi`**: `_register_py_class` (dynamic type index\nallocation, ancestor chain, TypeInfo insertion) and `_rollback_py_class`\n(cleanup on phase-2 failure).\n- **Cython `type_info.pxi`**: Field registration engine — computes\nper-field native layout from `parent_type_info.total_size`, obtains C\ngetter/setter function pointers, and registers via\n`TVMFFITypeRegisterField`. Installs `MakeFFINew`/`RegisterAutoInit`.\n- **Python `field.py`**: Pure-Python `Field` descriptor with `__slots__`\nmatching stdlib `dataclasses.field()` signature, plus `KW_ONLY` sentinel\n(3.9-compat).\n\n## Behavioral Changes\n\n- `__post_init__` is now called after `__ffi_init__` if defined\n(previously silently ignored).\n- Dunder family-skip: defining any member of `{__eq__, __ne__}` or\n`{__lt__, __le__, __gt__, __ge__}` suppresses the entire family\u0027s\nauto-generation.\n\n## Test plan\n\n- [x] Python tests pass: `uv run pytest -vvs tests/python`\n- [ ] Full `@py_class` end-to-end tests (in follow-up commits)\n- [x] Pre-commit lints pass"
    },
    {
      "commit": "1968f9dc0527c93db348bcc3fb3238330c141f8d",
      "tree": "d37069967531687b493c3755c70717858d39f500",
      "parents": [
        "c33f1ecbc1bf3ba5da1bf28d57fc30ba25a0f3d6"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Thu Mar 19 21:31:14 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Mar 19 21:31:14 2026 -0700"
      },
      "message": "feat(cython): add TypeSchema type conversion with function-pointer dispatch (#504)\n\n## Summary\n\n- **`CAny` owned-value wrapper** (`object.pxi`): New `cdef class CAny`\nthat holds sole ownership of a `TVMFFIAny` value with proper\nref-counting, `to_py()` round-trip support, and `SmallStr`/`SmallBytes`\npromotion to canonical FFI types.\n- **`TypeSchema` enhancements** (`type_info.pxi`): Add\n`origin_type_index` field for resolved type index lookup,\n`from_annotation()` for Python type annotations (`int`, `list[int]`,\n`Optional[str]`, `Union`, `Callable`, CObject subclasses),\n`from_type_index()`, `to_json()`, `check_value()` and `convert()`\nmethods. Adds STL type converters (`std::vector`, `std::optional`,\n`std::variant`, etc.) to `_TYPE_SCHEMA_ORIGIN_CONVERTER`. Adds\n`_ORIGIN_TO_TYPE_INDEX` / `_TYPE_INDEX_TO_ORIGIN` bidirectional maps.\nMakes `TypeInfo.fields` optional, adds `TypeInfo.total_size` cached\nproperty, and adds `TypeField.ty` optional schema attribute.\n- **`_TypeConverter` dispatch engine** (`type_converter.pxi`): New\n806-line `cdef class _TypeConverter` with C function pointer dispatch\n(`ctypedef CAny (*_dispatch_fn_t)(...) except *`). Each converter\ncompiles to a single indirect C function call with zero Python attribute\nlookup. Includes 20+ leaf/composite converter functions for POD, Object,\nOptional, Union, Array, List, Map, Dict, tuple, Callable, Any. Supports\n`__ffi_convert__` type attribute delegation, iterative\n`__tvm_ffi_value__` protocol with depth limit (64), zero-copy container\nfast path (copy-on-first-change), and exception-based error signaling\nvia `_ConvertError`.\n- **Bug fix**: `_lookup_type_attr` now copies `AnyView` to owned `Any`\nto prevent use-after-free.\n- **Exports**: `CAny` exported from `tvm_ffi.__init__`; type stubs\nupdated in `core.pyi`.\n\n## Architecture / Interface Changes\n\n- `TypeSchema.convert(value) -\u003e CAny` and `TypeSchema.check_value(value)\n-\u003e None` are the new public entry points for type conversion/validation.\n- `TypeSchema.from_annotation(annotation)` bridges Python typing\nannotations to `TypeSchema`, enabling e.g.\n`TypeSchema.from_annotation(Optional[list[int]])`.\n- `TypeSchema.to_json()` enables JSON round-tripping of type\ndescriptors.\n- `_TypeConverter` is internal (`cdef class`), lazily built via\n`TypeSchema._converter` cached property. No public API surface beyond\n`check_value`/`convert`.\n\n## Breaking Changes\n\n- `TypeSchema.args` type changed from `tuple[TypeSchema, ...]` to\n`tuple[TypeSchema, ...] | None` (now `None` for leaf types without args,\nthough `__post_init__` normalizes most cases to `()`).\n- `TypeInfo.fields` type changed from `list[TypeField]` to\n`Optional[list[TypeField]]`.\n- `TypeSchema.__post_init__` now raises `ValueError` instead of\n`AssertionError` for invalid argument counts.\n\n## Test Plan\n\n- [x] `tests/python/test_type_converter.py`: 60+ test classes covering\nPOD type exact match and implicit conversions, object type hierarchy,\nOptional/Union/nested containers, marshal protocols\n(`__tvm_ffi_value__`, `__tvm_ffi_object__`, `ObjectConvertible`,\n`__tvm_ffi_int/float__`, `__dlpack_device__`, `__cuda_stream__`), cycle\ndetection and depth limits, `__ffi_convert__` registration and dispatch,\nCAny wrapper operations, `TypeSchema.from_annotation` for all Python\ntype annotations, zero-copy conversion paths, cross-type Array/List and\nMap/Dict, error message quality, int64 boundary validation, schema arity\nchecks, dtype parsing, and exception normalization.\n- [x] Cython compilation on all CI platforms (Linux x86_64 + aarch64,\nmacOS arm64, Windows)\n- [x] Rust FFI compatibility (no Rust changes, but verify `cargo test`\nstill passes)"
    },
    {
      "commit": "c33f1ecbc1bf3ba5da1bf28d57fc30ba25a0f3d6",
      "tree": "57d1ca0fa75175749144da986fbcfcc6596122e6",
      "parents": [
        "f98ce6d56a522b5e6b00865735643934af0e184d"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Wed Mar 18 22:00:40 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Mar 18 22:00:40 2026 -0700"
      },
      "message": "feat(ffi)!: add __ffi_convert__ type attribute and Python-defined type support (#503)\n\n## Summary\n\n- Introduce `__ffi_convert__` type attribute: a per-type `Function` that\nperforms typed `AnyView -\u003e TObjectRef` conversion via\n`TypeTraits::TryCastFromAnyView`, registered through\n`TypeAttrDef\u003cT\u003e()`\n- Add Python-defined type infrastructure in `dataclass.cc`:\n`PyClassDeleter`, `MakeFFINew` (calloc-based factory), field\ngetter/setter dispatch, and `__ffi_shallow_copy__` for deep-copy support\n- Register `__ffi_convert__` for all built-in static types (Object,\nString, Bytes, Error, Function, Shape, Tensor, Array, Map, List, Dict)\n- Expose `ffi.FunctionFromExternC` global function for Python-side\nconstruction of `Function` objects from raw C function pointers\n\n## Test plan\n\n- [x] Existing C++ tests pass (reflection, object creation,\nserialization)\n- [x] Existing Python tests pass (c_class / py_class decorator\nintegration)\n- [x] CI lint (clang-format, clang-tidy) passes on changed files\n- [x] Integration testing with Python-side py_class decorator\n\n**BREAKING CHANGE:** Object base type registration now explicitly sets\n`structural_eq_hash_kind` to `kTVMFFISEqHashKindUnsupported`, which may\naffect types that previously inherited an uninitialized default."
    },
    {
      "commit": "f98ce6d56a522b5e6b00865735643934af0e184d",
      "tree": "9f430b84ef01e736d4f9f9272e700b2d5e64cbb8",
      "parents": [
        "e268eb1d2d55ae97bdaab7ab52f381f436fd0c82"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Mar 10 16:12:38 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Mar 10 16:12:38 2026 -0700"
      },
      "message": "feat(cython): expose additional C API symbols in base.pxi (#502)\n\n## Summary\n\n- Add Cython declarations for type-registration functions\n(`TVMFFITypeGetOrAllocIndex`, `TVMFFITypeRegisterField`,\n`TVMFFITypeRegisterMetadata`, `TVMFFITypeRegisterAttr`,\n`TVMFFIErrorSetRaisedFromCStr`) so Python-side type registration can\ncall these symbols directly through Cython\n- Add missing field-flag constants (`SEqHashIgnore`, `SEqHashDef`,\n`ReprOff`, `CompareOff`, `HashOff`) and the `TVMFFISEqHashKind` enum\n- Fix `TVMFFITypeMetadata.total_size` type (`int64_t` -\u003e `int32_t`) and\nadd `structural_eq_hash_kind` field to match the C struct layout\n- Add `cause_chain` and `extra_context` fields to the error info struct\n\n## Test plan\n\n- [ ] Existing CI tests pass (no behavioral change, declarations only)\n- [ ] Verify Cython compilation succeeds with the new declarations via\n`uv pip install --force-reinstall --verbose -e .`\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "e268eb1d2d55ae97bdaab7ab52f381f436fd0c82",
      "tree": "6319d0413bf6d00875036b02e5c6f97ce3212839",
      "parents": [
        "10dc59d196c8a88371a73a3fdc43d3400c0c0427"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Mar 10 13:48:04 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Mar 10 13:48:04 2026 -0700"
      },
      "message": "feat(ffi)!: centralize object creation with CreateEmptyObject/HasCreator (#501)\n\n## Summary\n\n- Add `CreateEmptyObject()` and `HasCreator()` inline helpers in\n`function.h` that unify the two-step \"check creator, call creator\"\npattern. These try the native `metadata-\u003ecreator` fast path first, then\nfall back to the `__ffi_new__` type attribute for Python-defined types.\n- Deduplicate four call sites in `creator.h`, `init.h`,\n`reflection_extra.cc`, and `serialization.cc` to use the new centralized\nhelpers.\n- Qualify bare `details::` references to `::tvm::ffi::details::` in\nreflection headers (`overload.h`, `registry.h`, `init.h`) to prevent\nADL/lookup ambiguity when included from other namespaces.\n\n## Test plan\n\n- [x] Existing C++ tests pass (object creation via reflection,\nserialization roundtrip)\n- [x] Existing Python tests pass (c_class / py_class decorator,\nreflection-based construction)\n- [x] CI lint (clang-format, clang-tidy) passes on changed headers"
    },
    {
      "commit": "10dc59d196c8a88371a73a3fdc43d3400c0c0427",
      "tree": "f8bd82b5aa66b42b7abe5b81b3c7a0c2e521820b",
      "parents": [
        "721d87816152e4a1cdc5c7906b116d46007699f8"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Mar 10 10:41:32 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Mar 10 10:41:32 2026 -0700"
      },
      "message": "feat(c_api)!: extend TVMFFIFieldInfo setter to support FunctionObj dispatch (#500)\n\nAdd `kTVMFFIFieldFlagBitSetterIsFunctionObj` (bit 11) to\n`TVMFFIFieldFlags`.\nWhen this flag is set, the `setter` member of `TVMFFIFieldInfo` holds a\n`TVMFFIObjectHandle` pointing to a `FunctionObj`, rather than a raw\n`TVMFFIFieldSetter` function pointer. The `FunctionObj` is invoked with\n`(field_addr_as_OpaquePtr, value_as_AnyView)`.\n\n**Motivation.** The existing `TVMFFIFieldSetter` signature\n`int (*)(void*, const TVMFFIAny*)` is a static C function pointer, which\ncannot represent custom setter logic defined at runtime (e.g. a\nPython-side\n`__ffi_convert__` wrapped in a `FunctionObj`). This change lets\nreflection\nfield definitions carry arbitrary callable setters while preserving full\nbackward compatibility for the common case.\n\n## Architecture\n\n- **`c_api.h`**: Change `TVMFFIFieldInfo::setter` from\n`TVMFFIFieldSetter`\n  to `void*` to accommodate both the function pointer (default) and the\n  `FunctionObj` handle (when the new flag is set).\n- **`reflection/accessor.h`**: Introduce `CallFieldSetter()` -- a\ncentral\n  dispatch helper that checks the flag and either casts back to\n`TVMFFIFieldSetter` or calls `TVMFFIFunctionCall`. Uses\nvalue-initialization\n(`TVMFFIAny args[2]{}`, `TVMFFIAny result{}`) instead of manual zeroing.\n- **`reflection/registry.h`, `reflection/overload.h`**: Cast the\ntemplate-\ngenerated `FieldSetter\u003cT\u003e` to `void*` when populating `TVMFFIFieldInfo`.\n- **`src/ffi/object.cc` (`TypeTable`)**: `RegisterTypeField` retains\n  `FunctionObj` setters via `any_pool_` (wrapping the handle in an `Any`\n  copied from a `TVMFFIAny`) so they survive in the type table without\n  manual ref-count management or a custom `~Entry` destructor.\n- **`tvm_ffi_python_helpers.h`**: `SetField` gains a `field_flags`\nparameter\nand mirrors the same dispatch logic on the Cython fast-path, also using\n  value-initialization for `TVMFFIAny` locals.\n\n## Public Interfaces\n\n- **`TVMFFIFieldInfo::setter`** type changes from `TVMFFIFieldSetter` to\n  `void*`. This is an ABI-breaking change for code that reads `setter`\n  directly (uncommon outside the framework itself).\n- **`TVMFFIFieldFlagBitMask`** gains\n`kTVMFFIFieldFlagBitSetterIsFunctionObj\n  \u003d 1 \u003c\u003c 11`.\n- **`TVMFFIPyCallFieldSetter`** gains a new `int64_t field_flags`\nparameter\n  (Cython-internal, not user-facing).\n\n## Behavioral Changes\n\n- All existing field setters continue to work unchanged; the new flag\n  defaults to off, preserving the function-pointer path.\n- When the flag is on, setter dispatch goes through\n`TVMFFIFunctionCall`,\nwhich adds one level of indirection but enables runtime-defined setters.\n- `FunctionObj` setter handles are retained in the type table via\n`any_pool_`\n  to prevent premature release.\n\n## Tests\n\nTests skipped (cherry-pick PR with review fixes only). Existing C++ and\nPython reflection tests cover the default (function pointer) path. The\n`FunctionObj` setter path will be exercised by downstream commits that\nwire\n`__ffi_convert__` through this mechanism.\n\n**BREAKING CHANGE:** `TVMFFIFieldInfo::setter` is now `void*` instead of\n`TVMFFIFieldSetter`."
    },
    {
      "commit": "721d87816152e4a1cdc5c7906b116d46007699f8",
      "tree": "a37c0d5d1cf521dc8d6c54f69212ddd31e530d5f",
      "parents": [
        "8255069663aad60ae24876a592ae4282cc91733e"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Mar 06 16:29:13 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Mar 06 16:29:13 2026 -0800"
      },
      "message": "fix(python): remove broken __instancecheck__/__subclasscheck__ from _ObjectSlotsMeta (#498)\n\n## Summary\n\n- Remove `__instancecheck__` and `__subclasscheck__` from\n`_ObjectSlotsMeta` in `python/tvm_ffi/cython/object.pxi`. These methods\nunconditionally returned `True` for any `CObject` instance/subclass\nregardless of which class was being checked, causing incorrect behavior\n(e.g., `isinstance(Map(...), Array)` returning `True`).\n- The methods are unnecessary because all objects returned from C++ are\nalways constructed as proper `Object` subclasses, so standard Python\nMRO-based `isinstance`/`issubclass` checks work correctly.\n- Update `test_dataclass_init.py` to assert correct behavior (parent is\nnot an instance of child).\n- Add 22 new regression tests in `TestIsinstanceIssubclass` covering\ncontainers, inheritance, and cross-hierarchy `isinstance`/`issubclass`\nchecks.\n\n## Test plan\n\n- [x] All 1517 existing Python tests pass\n- [x] 22 new tests verify correct isinstance/issubclass behavior for\ncontainers (Array, List, Map, Dict), inheritance hierarchies, and\ncross-hierarchy checks\n- [x] Pre-commit hooks pass (ruff, cython-lint, ty, etc.)"
    },
    {
      "commit": "8255069663aad60ae24876a592ae4282cc91733e",
      "tree": "b6b5dc88ab89a71547550717752d345c46b51959",
      "parents": [
        "bb13eaa3a36eecb46fc1437b410338b7d2a9488b"
      ],
      "author": {
        "name": "William Arnold",
        "email": "7565007+Aphoh@users.noreply.github.com",
        "time": "Wed Mar 04 08:23:45 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Mar 04 11:23:45 2026 -0500"
      },
      "message": "[FIX] Fix 3 deny-level clippy lints in Rust bindings (#496)\n\n## Summary\n\nFix 3 deny-level clippy lints in the Rust bindings that block `cargo\nclippy` from passing cleanly.\n\n## Changes\n\n### 1. `data_as_slice_mut(\u0026self)` → `data_as_slice_mut(\u0026mut self)`\n\n**Lint:** `clippy::mut_from_ref`\n\nThe original signature returned `\u0026mut [T]` from `\u0026self`. This allows\ncreating aliased mutable references through multiple shared borrows —\nwhich is unsound. Changing to `\u0026mut self` lets the borrow checker\nenforce exclusivity.\n\nPer the book\u0027s [\"Creating a Safe Abstraction over Unsafe\nCode\"](https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html) section:\na function that wraps unsafe code does not need to be marked `unsafe fn`\nif it validates its own preconditions. Here the signature (`\u0026mut self`)\nenforces the key invariant, and the body validates dtype, device, and\ncontiguity before calling `from_raw_parts_mut`.\n\n### 2. `with_stream` → `unsafe fn with_stream`\n\n**Lint:** `clippy::not_unsafe_ptr_arg_deref`\n\nTakes a `TVMFFIStreamHandle` (`*mut c_void`) and passes it to the C\nfunction `TVMFFIEnvSetStream`. The book says: \"just because a function\ncontains unsafe code doesn\u0027t mean we need to mark the entire function as\nunsafe.\" But that only applies when the function can validate its own\npreconditions. Here it cannot — there is no way to verify the stream\nhandle is valid (CUDA stream handles are opaque with no validation API).\nThe caller must uphold that invariant, so the function must be `unsafe\nfn`.\n\n### 3. `from_extern_c` → `unsafe fn from_extern_c`\n\n**Lint:** `clippy::not_unsafe_ptr_arg_deref`\n\nTakes a `*mut c_void` handle, a C function pointer (`safe_call`), and an\noptional `deleter`, all forwarded to `TVMFFIFunctionCreate`. The\nfunction cannot verify that the handle is valid, that `safe_call` is\ncompatible with it, or that `deleter` will correctly free it. These are\ninvariants the caller must uphold — same reasoning as `with_stream`."
    },
    {
      "commit": "bb13eaa3a36eecb46fc1437b410338b7d2a9488b",
      "tree": "bf13e9f93961b12ae210cf1d506f5cb018f674dd",
      "parents": [
        "dad4c402c1dbd8321a53f8f7501f227cbb067117"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Mon Mar 02 14:58:27 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 02 14:58:27 2026 -0800"
      },
      "message": "doc: add dataclass reflection guide and update related docs (#494)\n\n## Summary\n\nAdd a comprehensive guide for the dataclass-style reflection system\n(`ObjectDef`, field traits, auto-init, deep copy, repr, hashing,\ncomparison) and update the Sphinx documentation configuration and\ncross-references.\n\n## Changes\n\n### New documentation\n\n- **`docs/guides/dataclass_reflection.rst`** — A 467-line guide\ncovering:\n- Quick start: defining a C++ object with `ObjectDef`, using it from\nPython with full dataclass semantics.\n- Auto-generated constructors: how `__ffi_init__` is synthesized from\nreflected fields, including positional, optional, and keyword-only\nparameter ordering.\n- Field traits reference: `refl::default_()`, `refl::default_factory()`,\n`refl::kw_only()`, `refl::init()`, `refl::repr()`, `refl::hash()`,\n`refl::compare()`, `refl::Metadata`.\n- Dataclass operations: `DeepCopy`, `ReprPrint`, `RecursiveHash`,\n`RecursiveEq` with behavioral details (iterative DFS, cycle handling,\nDAG caching).\n- Custom hooks via `TypeAttrDef` for hash, equality, comparison, and\nrepr overrides.\n  - Python `c_class` decorator and `@register_object` delegation.\n- Inheritance semantics for field composition across parent/child object\nhierarchies.\n\n### Sphinx configuration updates (`docs/conf.py`)\n\n- Exclude `tvm::ffi::reflection::default_` and\n`tvm::ffi::reflection::default_factory` from Doxygen symbol output\n(these are user-facing helpers that cause Doxygen parse noise).\n- Fix `_link_inherited_members` to rewrite `.CObject` references as\n`.Object` in cross-reference links, correcting broken autodoc\ninherited-member links.\n- Add `_move`, `__move_handle_from__`, and\n`__init_handle_by_constructor__` to `_autodoc_always_show`, ensuring\nthese low-level Object lifecycle methods appear in auto-generated API\ndocs.\n\n### Cross-reference fixes in existing docs\n\n- **`docs/concepts/object_and_class.rst`**: Update\n`refl::DefaultValue(0)` to `refl::default_(0)` to match the current\npreferred API name.\n- **`docs/guides/export_func_cls.rst`**: Replace broken\n`:cpp:class:\\`tvm::ffi::reflection::init\\`` Sphinx cross-reference with\ninline code literal `` ``init\u003cArgs...\u003e()`` `` (the template alias does\nnot resolve as a Doxygen class).\n\n### TOC integration\n\n- **`docs/index.rst`**: Insert `guides/dataclass_reflection.rst` into\nthe Guides toctree between `export_func_cls` and `kernel_library_guide`.\n\n## Behavioral changes\n\nNone. This is a documentation-only change with no code modifications.\n\n## Test evidence\n\nDocumentation-only PR; no runtime behavior is affected. The guide\u0027s code\nexamples are consistent with the existing C++ reflection API\n(`ObjectDef`, field traits) and Python `c_class`/`register_object`\nimplementations validated by the existing test suite\n(`tests/python/test_dataclass.py`, `tests/cpp/test_reflection.cc`).\n\n### Untested corner cases\n\n- Sphinx build with the new RST file has not been verified in CI yet\n(will be validated by the doc-build CI job).\n- The `.CObject` -\u003e `.Object` rewrite in `_link_inherited_members` is a\nstring replacement; edge cases where a class legitimately contains\n\"CObject\" in its qualified name would be incorrectly rewritten (none\nexist in the current codebase)."
    },
    {
      "commit": "dad4c402c1dbd8321a53f8f7501f227cbb067117",
      "tree": "359acf43113c7df8092c6fda140f83bc2e7538dc",
      "parents": [
        "6973d225eb3c67a7c306e36b20a100c5e9ff46f7"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Mar 01 19:03:55 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Mar 01 22:03:55 2026 -0500"
      },
      "message": "test(python): add regression test for register_object __init__ wiring (#493)\n\n## Summary\n\nAdd a regression test for the `register_object` `__init__` wiring that\nprevents a NULL-handle segfault.\n\n## Root Cause\n\n`CObject` (Cython extension type) has a custom `tp_new`, so CPython\u0027s\n`object.__init__` silently ignores extra positional arguments. Before\n`_install_init` was wired into `register_object` (#491), calling\n`TestIntPair(1, 2)` fell through to `object.__init__`, producing\n`chandle \u003d NULL`. Any subsequent field access (e.g. `pair.a`)\ndereferences `chandle + field_offset` → **segfault**.\n\n## Test Coverage\n\nThe new `test_register_object_wires_init` verifies:\n\n1. Construction via the wired `__init__` yields a live (non-NULL) handle\nwith correct field values.\n2. `__new__` alone leaves `chandle` at 0, confirming `__init__` is the\nonly path that creates the C++ object.\n\nThe test does not exercise the actual segfault (which would crash the\nrunner); the NULL-handle assertion is the safe proxy.\n\n## Test Plan\n\n- [x] `pytest -xvs\ntests/python/test_object.py::test_register_object_wires_init` — passed"
    },
    {
      "commit": "6973d225eb3c67a7c306e36b20a100c5e9ff46f7",
      "tree": "c10ead3f6d4328324cb43a7dd35d2244cce014e8",
      "parents": [
        "bad3896fcd7b49a350978ec0be34926479341188"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Mar 01 16:11:36 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Mar 01 16:11:36 2026 -0800"
      },
      "message": "feat(python): wire __init__ from C++ reflection in register_object and stubgen (#491)\n\n## Summary\n\nWire `__init__` from C++ reflection metadata in both `register_object`\n(runtime) and `tvm-ffi-stubgen` (static stubs), so that registered\nclasses with `refl::init()` work out of the box without `@c_class`.\n\n## Architecture\n\n- **`stub/utils.py`**: New `InitFieldInfo` / `ObjectInfo.gen_init()`\nwalk the TypeInfo parent chain to collect `c_init`, `c_kw_only`,\n`c_has_default` flags per field, emitting typed `__init__` stubs via\n`_gen_auto_init` (KWARGS protocol with proper signature) or\n`_gen_c_init` (positional pass-through from `__c_ffi_init__`).\n- **`stub/codegen.py`**: `generate_object()` now calls `gen_init()` and\ninjects the result into the `TYPE_CHECKING` block before method stubs.\n- **`registry.py`**: `register_object._register()` calls\n`_install_init(cls, enabled\u003dTrue)` after `_add_class_attrs`, wiring\n`__init__` → `__ffi_init__` for any class whose C++ `ObjectDef`\nregistered `refl::init()`.\n- **`_install_init`**: When `enabled\u003dTrue` and no `__ffi_init__` exists,\nreturns silently instead of installing a TypeError guard —\nbackward-compatible for `Object()` and unregistered subclasses. The\n`enabled\u003dFalse` guard (used by `@c_class(init\u003dFalse)`) is unchanged.\n- Removed duplicate `_install_init` definition that shadowed the primary\none after rebase.\n\n## Public Interfaces\n\n- `register_object` now auto-wires `__init__` when C++ `__ffi_init__`\nexists; previously only `@c_class` did this.\n- `core.pyi`: Added `TypeField.c_init`, `c_kw_only`, `c_has_default` and\n`TypeInfo.type_ancestors` stubs.\n- Slots docstrings updated: recommend `__slots__ \u003d (\"__dict__\",)`\ninstead of the removed `slots\u003dFalse` metaclass keyword.\n\n## Behavioral Changes\n\n- Registered classes with `__ffi_init__` (non-auto-init) get `__init__ \u003d\n__ffi_init__` automatically — fixes `IntPair(1, 2)` in\n`examples/python_packaging`.\n- Classes without `__ffi_init__` keep default `object.__init__` behavior\n(no guard installed).\n- `@c_class(init\u003dFalse)` still installs a `TypeError` guard as before.\n- 30 unnecessary `ty: ignore` comments removed after stubgen generates\nproper `__init__` signatures.\n\n## Test Plan\n\n- [x] Pre-commit hooks pass (ruff check, ruff format, ty check,\ncython-lint, clang-format, ASF headers)\n- [x] Full `pytest tests/python` (requires build)\n- [x] `examples/python_packaging` end-to-end (requires build + `uv pip\ninstall`)\n- [x] C++ tests unaffected (no C++ changes)\n\n## Untested Edge Cases\n\n- stubgen `_gen_c_init` on packages whose shared library is not loaded\nat stubgen time (the metadata would be unavailable; no crash, just no\n`__init__` emitted).\n- Interaction of auto-wired `__init__` with `__init_subclass__` hooks on\ndeeply nested Object hierarchies."
    },
    {
      "commit": "bad3896fcd7b49a350978ec0be34926479341188",
      "tree": "926f29dae90d0dd7baacb20f03d0bc629e14183e",
      "parents": [
        "5c0deb94a9a8e9a56293ded341f0d4b0bcb7ba5b"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sun Mar 01 14:55:28 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Mar 01 11:55:28 2026 -0800"
      },
      "message": "[FIX] Fix the config loading in windows case (#490)\n\nThis PR fixes the config loading in windows case, sometimes in wheel\nsettings the testcase may still need to load core.pyd, so we by default\nload the library in config mode when it is windows."
    },
    {
      "commit": "5c0deb94a9a8e9a56293ded341f0d4b0bcb7ba5b",
      "tree": "dd20a5901b85b6784163b8d424f894fc4df3243d",
      "parents": [
        "e5f3af7bb83e6461c45d08117e4eaabe51add3b1"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sat Feb 28 19:02:14 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 28 19:02:14 2026 -0500"
      },
      "message": "[FEAT] Skip imports in config mode (#489)\n\nThis PR detects and skips import in config mode,\nreducing the overall time and dependency needed invoking tvm_ffi.config\n\n"
    },
    {
      "commit": "e5f3af7bb83e6461c45d08117e4eaabe51add3b1",
      "tree": "90826761ae79c0ca9d017d50d8be071e9dd1f51a",
      "parents": [
        "b1abaeac7103606a458d2bb91438652030d5ae88"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Feb 28 12:03:37 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 28 15:03:37 2026 -0500"
      },
      "message": "feat(python): reimplement c_class as register_object + structural dunders (#488)\n\n## Summary\n\nRewrite the `@c_class` decorator from a thin `register_object`\npass-through into\na `dataclass`-style decorator that combines FFI type registration with\nstructural\ndunder methods derived from C++ reflection metadata.\n\n- **`@c_class` now installs structural dunders** — `__init__`,\n`__repr__`, `__eq__`/`__ne__`,\n`__hash__`, and ordering operators (`__lt__`, `__le__`, `__gt__`,\n`__ge__`) — all\ndelegating to the corresponding C++ recursive operations (`RecursiveEq`,\n`RecursiveHash`,\n  `RecursiveLt`, etc.).\n- **`@dataclass_transform` decorator** added for IDE/type-checker\nsupport (pyright, mypy).\n- **Migrated all test objects** in `tvm_ffi.testing` from\n`@register_object` to `@c_class`.\n\n## Architecture\n\n- `c_class.py`: decorator accepts `init`, `repr`, `eq`, `order`,\n`unsafe_hash`\nparameters. Delegates to `register_object` +\n`_install_dataclass_dunders`.\n- `registry.py`: `_install_dataclass_dunders` installs dunders on class;\n  `_install_init` synthesizes reflection-based `__init__` or guard;\n`_make_init` / `_make_init_signature` builds `inspect.Signature` from\nC++ field\n  metadata (respecting `kw_only`, `has_default`, `c_init` traits).\n  `_is_comparable` centralises the bidirectional isinstance guard.\n- Each installed dunder checks `cls.__dict__` before setting, preserving\nuser-defined\n  overrides.\n- `__eq__`/`__ne__`/ordering return `NotImplemented` for unrelated\ntypes, following\n  Python data model conventions.\n\n## Public Interfaces\n\n- `@c_class(type_key, *, init, repr, eq, order, unsafe_hash)` — new\nkeyword\narguments; old usage `@c_class(\"key\")` continues to work with sensible\ndefaults\n  (`init\u003dTrue`, `repr\u003dTrue`, others off).\n- No breaking changes — `eq`, `order`, `unsafe_hash` default to `False`.\n\n## Test Plan\n\n- [x] New `test_dataclass_c_class.py` (26 tests): custom init\npreservation,\nauto-generated init with defaults, structural equality (reflexive,\nsymmetric),\nhash (dict key, set dedup), ordering (reflexive, antisymmetric),\ndifferent-type\nreturns `NotImplemented`, subclass equality, `kw_only` from C++\nreflection,\n  `init_subset`, derived-derived defaults.\n- [x] Renamed `test_copy.py` → `test_dataclass_copy.py` with additional\ncycle/Shape\n  coverage and `deep_copy.cc` branch-coverage tests.\n- [x] `uv run pytest -vvs tests/python` — 960 passed, 23 skipped, 1\nxfailed.\n- [x] `sphinx-build -W --keep-going -b html docs docs/_build/html` —\nbuild succeeded.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)"
    },
    {
      "commit": "b1abaeac7103606a458d2bb91438652030d5ae88",
      "tree": "a99d33bc2c826090b945d04d50c6f3bfdcb05a24",
      "parents": [
        "ac80ea39735f0284451141837de23dff99b95129"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Feb 28 03:51:09 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 28 06:51:09 2026 -0500"
      },
      "message": "feat(python): wire C++ auto-generated __ffi_init__ to Python __init__ (#486)\n\n## Summary\n\n- Expose `RecursiveHash` to the Python FFI API (`_ffi_api.py` stub +\n`__all__`)\n- Add `TestHash` and `TestCustomHash` reflected test fixture classes to\n`tvm_ffi.testing`\n- Add comprehensive `test_dataclass_hash.py` covering the full\n`RecursiveHash` contract\n\n## Architecture\n\n- Two new reflected test fixture classes registered via C++ reflection:\n- **`TestHash`** (`testing.TestHash`): exercises `Hash(false)` field\nexclusion on `hash_ignored`\n- **`TestCustomHash`** (`testing.TestCustomHash`): exercises\n`__ffi_hash__` custom hook (hashes only `key`, ignores `label`)\n\n## Test Coverage\n\n| Category | What\u0027s tested |\n|---|---|\n| Primitives | int, float, bool, str, bytes, None, DataType, Device |\n| NaN handling | All NaN payloads hash equal; canonicalization in nested\ncontainers |\n| Signed zero | `+0.0` and `-0.0` hash identically |\n| Containers | Array, List, Shape, Map, Dict —\nequal/different/empty/nested |\n| Reflected objects | TestIntPair, inherited fields (3-level), objects\nwith container fields |\n| Field exclusion | `Hash(false)` via TestHash; `Compare(false)` implies\nhash-off |\n| Custom hooks | `__ffi_hash__` via TestCustomHash and TestCustomCompare\n|\n| Cycle detection | Self-referential List/Dict hashing succeeds\ngracefully |\n| Consistency law | `RecursiveEq(a, b) ⟹ RecursiveHash(a) \u003d\u003d\nRecursiveHash(b)` — primitives, containers, reflected objects, custom\nhooks |\n| Aliasing invariants | Shared vs duplicated references produce\nidentical hashes |\n| Recursion depth | 127 and 1000 levels of nesting (iterative heap-based\nstack) |\n| DAG scaling | Shared binary DAG hashing is linear, not exponential\n(warm-up + averaged) |\n| Guard | `__ffi_eq__` without `__ffi_hash__` raises ValueError |\n\n## Test Plan\n\n- [x] `uv run pytest -vvs tests/python/test_dataclass_hash.py`"
    },
    {
      "commit": "ac80ea39735f0284451141837de23dff99b95129",
      "tree": "132bc0aa8f618edb617a46256e9089a277811c39",
      "parents": [
        "5796ff4b6b1a765a9181addaeb56ba9b253cfa8b"
      ],
      "author": {
        "name": "ctuu",
        "email": "ctuu1s@outlook.com",
        "time": "Sat Feb 28 10:20:11 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 18:20:11 2026 -0800"
      },
      "message": "[FEAT] Add CMake namespace aliases for source dependency builds (#479)\n\n## Summary\nAdd namespace-qualified ALIAS targets (tvm_ffi::header, tvm_ffi::shared,\ntvm_ffi::static) that point to the in-tree build targets\n(tvm_ffi_header, tvm_ffi_shared, tvm_ffi_static).\n\n## Problem\nWhen tvm-ffi is used as a source dependency, `tvm_ffi_configure_target`\nexpects `tvm_ffi::header` / `tvm_ffi::shared` targets to exist. However,\nthese are only created by the package config file\n(`cmake/tvm_ffi-config.cmake`), which is not included during source\nbuilds. Downstream projects using source dependencies cannot use these\ntargets.\n\n## Solution\nCreate ALIAS targets in both:\n- Top-level `CMakeLists.txt` for `tvm_ffi::header`\n- `cmake/Utils/Library.cmake` for `tvm_ffi::static` and\n`tvm_ffi::shared` (created by `tvm_ffi_add_target_from_obj`)\n\nThis ensures the namespace-qualified names are available in both source\nand package builds."
    },
    {
      "commit": "5796ff4b6b1a765a9181addaeb56ba9b253cfa8b",
      "tree": "7c3a7e389e10d1b083bd21574e640870149be499",
      "parents": [
        "b87196f998868b2dfb76a7bf2be8795f75b099b8"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 27 17:11:28 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 17:11:28 2026 -0800"
      },
      "message": "test(python): add comprehensive RecursiveHash test suite (#485)\n\n## Summary\n\n- Expose `RecursiveHash` to the Python FFI API (`_ffi_api.py` stub +\n`__all__`)\n- Add `TestHash` and `TestCustomHash` reflected test fixture classes to\n`tvm_ffi.testing`\n- Add comprehensive `test_dataclass_hash.py` covering the full\n`RecursiveHash` contract\n\n## Architecture\n\n- Two new reflected test fixture classes registered via C++ reflection:\n- **`TestHash`** (`testing.TestHash`): exercises `Hash(false)` field\nexclusion on `hash_ignored`\n- **`TestCustomHash`** (`testing.TestCustomHash`): exercises\n`__ffi_hash__` custom hook (hashes only `key`, ignores `label`)\n\n## Test Coverage\n\n| Category | What\u0027s tested |\n|---|---|\n| Primitives | int, float, bool, str, bytes, None, DataType, Device |\n| NaN handling | All NaN payloads hash equal; canonicalization in nested\ncontainers |\n| Signed zero | `+0.0` and `-0.0` hash identically |\n| Containers | Array, List, Shape, Map, Dict —\nequal/different/empty/nested |\n| Reflected objects | TestIntPair, inherited fields (3-level), objects\nwith container fields |\n| Field exclusion | `Hash(false)` via TestHash; `Compare(false)` implies\nhash-off |\n| Custom hooks | `__ffi_hash__` via TestCustomHash and TestCustomCompare\n|\n| Cycle detection | Self-referential List/Dict hashing succeeds\ngracefully |\n| Consistency law | `RecursiveEq(a, b) ⟹ RecursiveHash(a) \u003d\u003d\nRecursiveHash(b)` — primitives, containers, reflected objects, custom\nhooks |\n| Aliasing invariants | Shared vs duplicated references produce\nidentical hashes |\n| Recursion depth | 127 and 1000 levels of nesting (iterative heap-based\nstack) |\n| DAG scaling | Shared binary DAG hashing is linear, not exponential\n(warm-up + averaged) |\n| Guard | `__ffi_eq__` without `__ffi_hash__` raises ValueError |\n\n## Test Plan\n\n- [x] `uv run pytest -vvs tests/python/test_dataclass_hash.py`"
    },
    {
      "commit": "b87196f998868b2dfb76a7bf2be8795f75b099b8",
      "tree": "9c6dd64e1cba655e3fbc3d59d1d62d73607b26de",
      "parents": [
        "6b39efbf381e48a8a42ab3779bc2adf587458fb3"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 27 16:33:25 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 19:33:25 2026 -0500"
      },
      "message": "feat(python): expose recursive compare to Python with comprehensive tests (#484)\n\n## Summary\n\n- Expose `RecursiveEq`, `RecursiveLt`, `RecursiveLe`, `RecursiveGt`,\n`RecursiveGe` C++ comparison functions to Python via `_ffi_api` typed\nstubs\n- Add three new testing dataclasses (`TestCompare`, `TestCustomCompare`,\n`TestEqWithoutHash`) to `tvm_ffi.testing`\n- Add comprehensive `test_dataclass_compare.py` (1272 lines, 101 test\ncases) covering recursive structural comparison end-to-end from Python\n\n## Architecture\n\n- **Python FFI surface**: `_ffi_api.py` gains five\n`Recursive{Eq,Lt,Le,Gt,Ge}` typed stubs plus `GetKwargsObject` and\n`MakeInit` (from upstream stub regeneration). These delegate to the C++\n`ffi.Recursive*` global functions already registered in the runtime.\n- **Testing infrastructure**: `tvm_ffi.testing` gains `TestCompare`\n(field-level `Compare(false)` opt-out), `TestCustomCompare` (custom\n`__ffi_eq__`/`__ffi_compare__` hooks comparing only `key`), and\n`TestEqWithoutHash` (equality without hash — exercises the hash-guard\npath where ordering falls back to reflection). All three are\n`@register_object`-decorated with C++ reflection stubs.\n\n## Public Interfaces\n\n- No public API changes. `RecursiveEq`/`RecursiveLt`/etc. are internal\n`_ffi_api` symbols used by tests; the C++ functions were already\nregistered on `main`.\n\n## Behavioral Changes\n\n- No runtime behavioral changes. This PR adds Python-side bindings and\ntests only.\n\n## Test Plan\n\n101 tests in `test_dataclass_compare.py` covering:\n\n- **Primitives**: int (including int64 extremes where naive subtraction\noverflows), float (signed zero, infinity), NaN (equality-only; ordering\nraises `TypeError`; payload-insensitive), bool, string (SmallStr/Str\nheap boundary, embedded NUL), bytes (SmallBytes/Bytes boundary, embedded\nNUL, high-bit)\n- **Special values**: `None` ordering (less than any non-None),\ntype-mismatch (eq returns `False`, ordering raises `TypeError`)\n- **Inline types**: `DataType`, `Device`\n- **Containers**: `Array`, `List`, `Map`, `Dict`, `Shape` — equality,\nlexicographic ordering, empty/prefix/length-mismatch, nested composition\n(3-level deep)\n- **Reflected objects**: `TestIntPair` field-by-field structural\ncomparison, `TestCompare` with `Compare(false)` field exclusion,\n`TestCustomCompare` with custom `__ffi_eq__`/`__ffi_compare__` hooks,\ncross-type object comparison, inherited fields (2- and 3-level\ninheritance)\n- **Cycle detection**: same-pointer identity (returns `True`), distinct\ncyclic `List`/`Dict` under equality (returns `True` via on-stack pair\nmemoization), distinct cyclic structures under ordering (raises\n`ValueError`)\n- **Ordering laws**: trichotomy (exactly one of lt/eq/gt),\nderived-operator consistency (le ↔ lt∨eq, ge ↔ gt∨eq, lt ↔ ¬ge, gt ↔\n¬le), antisymmetry, and O(n³) transitivity for Lt and Le over\n`TestIntPair` values\n- **Advanced**: `CompareOff` flag inside containers and nested objects,\n`EqWithoutHash` hash guard (eq-only hook with reflection fallback for\nordering), `Function` objects (no reflected fields → always equal),\ndepth-1000 nested singleton arrays (iterative stack)\n\n```\nuv run pytest -vvs tests/python/test_dataclass_compare.py\n# 101 passed, 0 failed\n```\n\n## Untested Edge Cases\n\n- Asymmetric cycles (`a → b → a` where the two sides have different\ncycle structure). The C++ `on_stack_` set tracks `(lhs, rhs)` pairs so\nthis should terminate correctly, but no explicit test covers it. Risk:\nlow.\n- `Tuple` and `Variant` containers are not exercised (no Python\nconstructor surface for `Variant` in `tvm_ffi`)."
    },
    {
      "commit": "6b39efbf381e48a8a42ab3779bc2adf587458fb3",
      "tree": "87fb346de3dd1a2f2b1373a2ba625b609ae01589",
      "parents": [
        "49a5d71a3145aee20b6cfbcb7a2f7d9feb25f2f7"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 27 14:17:43 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 14:17:43 2026 -0800"
      },
      "message": "refactor!: consolidate repr_print/deep_copy into dataclass.cc with recursive hash/compare APIs (#482)\n\n## Summary\n\n- **Consolidate** `deep_copy.cc` and `repr_print.cc` into a unified\n`dataclass.cc` backed by a shared iterative `ObjectGraphDFS` CRTP\nengine, eliminating duplicated graph-walking logic for cycle/DAG\nhandling.\n- **Add recursive hash/compare C++ APIs** (`RecursiveHash`,\n`RecursiveEq`, `RecursiveLt/Le/Gt/Ge`) as new public functions in\n`tvm::ffi` (via `dataclass.h`), with per-field opt-out through new\n`compare(false)` and `hash(false)` reflection traits.\n- **Auto-generate `__ffi_init__`** from reflection metadata: `ObjectDef`\ndestructor now auto-registers a packed init constructor when no explicit\n`refl::init\u003cArgs...\u003e` was supplied, using the type\u0027s creator + field\nanalysis (positional ordering, `kw_only`, defaults).\n\n## Architecture\n\n- New `include/tvm/ffi/extra/dataclass.h` — public C++ API for\n`DeepCopy`, `ReprPrint`, `RecursiveHash`, and relational comparisons.\n- New `include/tvm/ffi/reflection/init.h` —\n`MakeInit`/`RegisterAutoInit` for auto-generated packed constructors.\n- `include/tvm/ffi/extra/deep_copy.h` internalized →\n`src/ffi/object_internal.h`.\n- 4 new C ABI field flag bits: `CompareOff` (1\u003c\u003c7), `HashOff` (1\u003c\u003c8),\n`InitOff` (1\u003c\u003c9), `KwOnly` (1\u003c\u003c10).\n- New lowercase reflection traits: `repr`, `compare`, `hash`, `kw_only`,\n`init(bool)`, `default_`, `default_factory`.\n- Sentinel objects `ffi.GetInvalidObject` / `ffi.GetKwargsObject` for\nKWARGS calling convention.\n\n## Breaking Changes\n\n- `refl::Repr` renamed to `refl::repr` (lowercase). Downstream:\n`refl::Repr(false)` → `refl::repr(false)`.\n- `include/tvm/ffi/extra/deep_copy.h` removed from public headers.\n- `test_repr.py` renamed to `test_dataclass_repr.py`.\n\n## Test plan\n\n- [x] C++ tests: `test_reflection.cc` expanded with new trait coverage\n- [x] Python tests: `test_dataclass_repr.py` — repr, cycles, DAGs,\naddresses, special chars, containers, nested dataclasses\n- [x] CI: lint, clang-tidy, full test matrix (Linux x86_64/aarch64,\nmacOS arm64, Windows)"
    },
    {
      "commit": "49a5d71a3145aee20b6cfbcb7a2f7d9feb25f2f7",
      "tree": "6cb08bc92e805b88ea9c9bdfe81d1844704b8ce5",
      "parents": [
        "577b2949f2c6818c6e4430528ca11303fe024e78"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 27 12:34:54 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 12:34:54 2026 -0800"
      },
      "message": "feat(python)!: enforce __slots__\u003d() for Object subclasses via _ObjectSlotsMeta (#480)\n\n## Summary\n\n- Split Cython `Object` into `CObject` (extension type) + `Object`\n(Python class with `_ObjectSlotsMeta` metaclass) to enforce\n`__slots__\u003d()` across the entire Object hierarchy.\n- Remove the `slots: bool \u003d True` keyword argument from\n`_ObjectSlotsMeta`; subclasses that need a `__dict__` declare `__slots__\n\u003d (\"__dict__\",)` explicitly.\n- Simplify `Module.__getattr__` to store looked-up functions via\n`setattr` (into `__dict__` via `__slots__ \u003d (\"__dict__\",)`), letting\nnormal attribute lookup serve as cache.\n- Replace module-global `_REPR_PRINT` cache with local `_ffi_api` import\nin `object_repr()`.\n\n## Breaking Changes\n\n- All `Object` subclasses now enforce `__slots__\u003d()` by default. Code\nthat sets arbitrary instance attributes will raise `AttributeError`.\nMigrate by declaring needed slots explicitly (e.g., `__slots__ \u003d\n(\"__dict__\",)`).\n- `_ObjectSlotsMeta` no longer accepts `slots` keyword argument.\n- `DLDeviceType.kDLTrn` renumbered from 17→18; `kDLMAIA\u003d17` added.\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python` — 532 passed, 23 skipped, 1\nxfailed\n- [x] All pre-commit hooks pass (ruff, ty, cython-lint, etc.)\n- [x] C++ tests (no C++ changes in this PR)\n- [x] Rust tests (no Rust changes in this PR)"
    },
    {
      "commit": "577b2949f2c6818c6e4430528ca11303fe024e78",
      "tree": "2400c9630fdb593456ed9b8a48ccf6113cfa623f",
      "parents": [
        "adac5ebd0ad695fc77bf5113c8127a7298c1ed52"
      ],
      "author": {
        "name": "Yong Wu",
        "email": "yongcale@gmail.com",
        "time": "Fri Feb 27 11:25:57 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 11:25:57 2026 -0800"
      },
      "message": "chore(release): Version bump after release v0.1.9 (#481)\n\nVersion bump"
    },
    {
      "commit": "adac5ebd0ad695fc77bf5113c8127a7298c1ed52",
      "tree": "cd5ad529e02938ff6d0045289b1d08c8ba76d07c",
      "parents": [
        "b97ff1ae2abd21f5b8a368d5e04f34b53e3985bf"
      ],
      "author": {
        "name": "Gabriel Wu",
        "email": "13583761+lucifer1004@users.noreply.github.com",
        "time": "Sat Feb 28 00:02:43 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 28 00:02:43 2026 +0800"
      },
      "message": "feat: add cuLaunchKernelEx support (#476)\n\n"
    },
    {
      "commit": "b97ff1ae2abd21f5b8a368d5e04f34b53e3985bf",
      "tree": "ef2015e4dbe137a7fc0c0944aa080f92ddd8369e",
      "parents": [
        "a8f0540556794d39a7e260977948c6719a7648e2"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 27 03:43:55 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 27 06:43:55 2026 -0500"
      },
      "message": "refactor(dataclasses)!: remove Python-side field descriptor infrastructure (#478)\n\n## Summary\n\n- Remove the Python-side dataclass field descriptor system (`_utils.py`,\n`field.py`, complex `c_class.py`) that duplicated C++ reflection\nmetadata\n- Simplify `c_class` decorator to a thin pass-through to\n`register_object`\n- Fix `_add_class_attrs` to always override `__c_ffi_init__` per type,\npreventing inherited base-class constructors from masking derived-class\nconstructors\n\n## Architecture\n\nThe previous `c_class` decorator maintained a parallel Python-side field\ndescriptor system (`Field`, `KW_ONLY`, `default_factory`, codegen\u0027d\n`__init__`) that mirrored what C++ reflection already provides. This PR\nremoves that duplication:\n\n- **Deleted**: `_utils.py` (210 lines — `type_info_to_cls`,\n`fill_dataclass_field`, `method_init` codegen), `field.py` (169 lines —\n`Field` class, `KW_ONLY` sentinel, default factory wiring)\n- **Simplified**: `c_class.py` reduced from 190 to 36 lines — now\ndelegates directly to `register_object`\n- **Fixed**: `_add_class_attrs` in `registry.py` now always overrides\n`__c_ffi_init__` on each type (matching the existing\n`__ffi_shallow_copy__` override pattern), preventing a derived class\nfrom inheriting a base class constructor with the wrong field count\n\n## Breaking Changes\n\n- `field()`, `Field`, `KW_ONLY`, and `MISSING` are no longer exported\nfrom `tvm_ffi.dataclasses`\n- `c_class`-decorated classes must now explicitly inherit from `Object`\n(previously `_utils.type_info_to_cls` injected it)\n- `__init__` on decorated types uses the C++ FFI constructor directly\n(positional args in field order) instead of the Python codegen\u0027d init\nwith keyword-only and default factory support\n- The `init` and `kw_only` parameters of `c_class()` are removed\n\n## Test plan\n\n- [x] `tests/python/test_repr.py` updated — derived constructors use\npositional args\n- [x] `tests/python/test_dataclasses_c_class.py` deleted — tested\nremoved infrastructure\n- [x] Full CI pass on all platforms"
    },
    {
      "commit": "a8f0540556794d39a7e260977948c6719a7648e2",
      "tree": "00a2c08e22b4dfb9408bfee9212c206b42732de7",
      "parents": [
        "48d590ed878536b686cf35b263dac9b4f9464fad"
      ],
      "author": {
        "name": "Gabe Guralnick",
        "email": "gnguralnick@gmail.com",
        "time": "Wed Feb 25 14:19:12 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 25 17:19:12 2026 -0500"
      },
      "message": "[FIX] Prevent integer overflow in GetDataSize on 32-bit platforms (#475)\n\nOn 32-bit platforms (e.g. WASM), the intermediate multiplication `numel\n* dtype.bits * dtype.lanes` in `GetDataSize()` can overflow `size_t` for\nlarge tensors, even when the final byte count (after dividing by 8) fits\nwithin 32 bits.\n\nThis PR casts the intermediate computation to `uint64_t` to avoid the\noverflow, then casts the result back to `size_t`.\n\nI was experiencing this error when trying to run a model with webllm\nusing a runtime compiled by mlc-llm - the operation was overflowing,\ncausing the allocation of 0-byte buffers.\n\nCo-authored-by: Gabriel Guralnick \u003cgabriel@imbue.com\u003e"
    },
    {
      "commit": "48d590ed878536b686cf35b263dac9b4f9464fad",
      "tree": "3b32d7134453859291dbdc679e8d415ee588075b",
      "parents": [
        "c85fd42df6eae4ae0ec1aaa4ebb67ac859758cf5"
      ],
      "author": {
        "name": "Yong Wu",
        "email": "yongcale@gmail.com",
        "time": "Tue Feb 24 11:03:37 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Feb 24 11:03:37 2026 -0800"
      },
      "message": "chore(release): Add GPG Key from Yong Wu (#474)\n\nAdd key to the KEYS"
    },
    {
      "commit": "c85fd42df6eae4ae0ec1aaa4ebb67ac859758cf5",
      "tree": "348e336c6312fa2334b3f97cf61941098f2c2d5e",
      "parents": [
        "7786133167902a810dd4717fd0e7d39f4c6f7e99"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sun Feb 22 11:15:39 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Feb 22 08:15:39 2026 -0800"
      },
      "message": "[ABI] Add begin_index to TypeAttrColumn (#471)\n\nThis PR adds a begin_index field to TypeAttrColumn. The begin_index\nenables the type attributes to store narrowly a range of type indices\nwhich can be useful when type attribute is narrowed to specific subscope\nwhere objects are allocated continuously so we can optimize for space\nand locality.\n\nAs of now the accessor of the TypeAttrColumn is limited to extra/cc so\nimpact is limited. To be careful, we begin_index is set to 0 for next\nfew versions and will migrate to nonzero size in 1.0 (so i64 platform\nsize is compatible)"
    },
    {
      "commit": "7786133167902a810dd4717fd0e7d39f4c6f7e99",
      "tree": "0f7da2e1a9b52db8e3639b675b2c6cb3097f6265",
      "parents": [
        "49ff2aa32c407df92004bef37387822953c21496"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Feb 21 20:36:48 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 21 20:36:48 2026 -0800"
      },
      "message": "feat(stub): use distinct container type origins in type schema and stub generation (#469)\n\n## Summary\n\n- **Distinct container type origins**: TypeSchema now emits `Array`,\n`List`, `Map`, `Dict` instead of collapsing all sequence types to `list`\nand all mapping types to `dict`. This preserves the immutable\n(copy-on-write) vs mutable (shared-reference) distinction through the\nentire schema → annotation pipeline.\n- **Correct stub annotations**: Generated stubs now use\n`MutableSequence`/`MutableMapping` for `List`/`Dict` parameters and\n`Sequence`/`Mapping` for `Array`/`Map`, matching the actual Python ABCs\neach container implements.\n- **New containers concept page**: Added `docs/concepts/containers.rst`\ndocumenting all five container types, their mutability semantics, thread\nsafety, and usage guidance. Updated C++ and Python language guides with\nList and Dict sections.\n\n## Details\n\n### Type schema changes\n- `_TYPE_SCHEMA_ORIGIN_CONVERTER` in `type_info.pxi`: `ffi.Array` →\n`Array`, `ffi.List` → `List`, `ffi.Map` → `Map`, `ffi.Dict` → `Dict`\n- `TY_MAP_DEFAULTS` in `stub/consts.py`: `Array` → `Sequence`, `List` →\n`MutableSequence`, `Map` → `Mapping`, `Dict` → `MutableMapping`\n- Backward compat: raw `list`/`dict` origins still parse correctly in\n`TypeSchema`\n\n### Stub codegen improvements\n- Collision avoidance: when a function name matches a type import\nsuffix, the type import gets an alias (e.g. `_StructuralKey`) to avoid\nshadowing\n- D105 (undocumented-magic-method) added to global ruff ignore list —\ngenerated dunder stubs no longer need inline `# noqa` comments\n- New `DeepCopy` and `__ffi_shallow_copy__` stubs appear in generated\ncode\n\n### Documentation\n- New `docs/concepts/containers.rst` concept page\n- Updated `docs/concepts/any.rst` (List/Dict in type table)\n- Updated `docs/guides/cpp_lang_guide.md` (List, Dict sections)\n- Updated `docs/guides/python_lang_guide.md` (List, Dict, Tuple\nsections)\n- Updated `CLAUDE.md` and `.claude/skills/devtools/SKILL.md` (stub\ngeneration workflow)\n\n## Test plan\n\n- [x] `uv run pytest -vvs tests/python` — 543 passed, 22 skipped, 1\nxfailed\n- [x] `uv run pre-commit run --all-files` — 27/27 hooks passed\n- [x] `uv run ty check python/tvm_ffi/_ffi_api.py` — all checks passed\n(no more `invalid-type-form` error)\n- [x] CI: lint, clang-tidy, full test suite\n- [x] Verify Sphinx doc build renders new containers page correctly"
    },
    {
      "commit": "49ff2aa32c407df92004bef37387822953c21496",
      "tree": "1aae7eb8910a593c53ac7c0056ca9850f50ee495",
      "parents": [
        "37d0485b2058885bf4e7a486f7d7b2174a8ac1ce"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Feb 21 06:08:42 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 21 09:08:42 2026 -0500"
      },
      "message": "feat: add CLAUDE.md and dev server launch config (#468)\n\n## Summary\n- Add `CLAUDE.md` with project overview, build/test/lint instructions,\ncode conventions, and architecture notes for Claude Code\n- Add `.claude/launch.json` with Sphinx autobuild dev server\nconfiguration (port 8000)\n\n## Test plan\n- [x] Pre-commit hooks pass (ASF header, markdownlint, etc.)\n- [x] Verify `CLAUDE.md` content is accurate and useful for Claude Code\nsessions\n- [x] Verify `.claude/launch.json` correctly starts the docs dev server"
    },
    {
      "commit": "37d0485b2058885bf4e7a486f7d7b2174a8ac1ce",
      "tree": "eb2b4d8cef53c35cf58b40b05c579c0a471cceb2",
      "parents": [
        "07546c750337c73e1d74cf4e1a29c32fbee0c139"
      ],
      "author": {
        "name": "Hubert Lu",
        "email": "55214931+hubertlu-tw@users.noreply.github.com",
        "time": "Fri Feb 20 07:07:07 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 20 10:07:07 2026 -0500"
      },
      "message": "ROCm: fix DLPack current_work_stream and force addon override for Torch exchange API (#466)\n\n## Motivation\n\nOn ROCm, graph-capture-sensitive callers (for example SGLang JIT\nkernels) can hit stream mismatch behavior through the Torch DLPack\nexchange API path. In practice this shows up as HIP graph empty-capture\nwarnings and forced downstream workarounds in callers.\n\nWe want `tvm-ffi` to provide a correct ROCm stream callback and let\ndownstream projects remove ROCm-specific Python bridging code.\n\n## Reproducer\n\n### Minimal `tvm-ffi` reproducer\n\n- New test: `tests/python/test_current_work_stream_gpu.py`\n- It obtains `torch.Tensor.__dlpack_c_exchange_api__`, calls\n`current_work_stream`, and verifies stream identity against a\nnon-default torch stream.\n- It checks:\n  - `kDLCUDA` always\n  - `kDLROCM` on HIP runtime\n\n## Fix\n\n### 1) ROCm stream callback implementation\n\nFile:\n\n- `python/tvm_ffi/utils/_build_optional_torch_c_dlpack.py`\n\nChanges:\n\n- Include `ATen/hip/impl/HIPStreamMasqueradingAsCUDA.h` for ROCm builds.\n- In `CurrentWorkStream(...)`:\n  - ROCm build path now returns:\n- `c10::hip::getCurrentHIPStreamMasqueradingAsCUDA(device_id).stream()`\n  - CUDA build path remains:\n    - `at::cuda::getCurrentCUDAStream(device_id).stream()`\n\nThis aligns stream reporting with ROCm semantics used by PyTorch HIP\nstream handling.\n\n### 2) Ensure ROCm uses `tvm-ffi` addon API\n\nFile:\n\n- `python/tvm_ffi/_optional_torch_c_dlpack.py`\n\nChanges:\n\n- On ROCm (`torch.cuda.is_available() and torch.version.hip is not\nNone`), do not early-return just because torch already exposes\n`__dlpack_c_exchange_api__`.\n- Force loading/using the `tvm-ffi` addon capsule on ROCm so the fixed\ncallback is actually active.\n- NVIDIA/CUDA path remains unchanged.\n\n## Validation\n\n### `tvm-ffi` side\n\n- `python -m pytest -q tests/python/test_current_work_stream_gpu.py`\n- Result: pass\n\n### Downstream impact check (SGLang)\n\nTo verify this can remove divergence in SGLang JIT path, we temporarily\nremoved:\n\n- `hip_ensure_tvm_ffi_stream(...)`\n- `to_tvm_tensor_cached(...)`\nRef:\nhttps://github.com/sgl-project/sglang/pull/18992/changes/df80efb85eee5f5c2be4241865a77508ae0d7a69#diff-ff0d21f07b9d4c75f02741e8e63e4eee34a1bd24e8f74c7b6b96f0f19ee97bd8R204-R233"
    },
    {
      "commit": "07546c750337c73e1d74cf4e1a29c32fbee0c139",
      "tree": "622882d429d54c5d5375c74fca27dc6fd83daa04",
      "parents": [
        "35cbc3274cf4b02d8d2e34d2510be5b34d0046ea"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Fri Feb 20 10:03:16 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 20 10:03:16 2026 -0500"
      },
      "message": "[COMPACT][TEMP] Array compact temp fix  (#467)\n\nIn the 0.1.19 patch, we changed the operator[] to return T(from const\nT). This is the right change. However, flashinfer depends on an sutble\nimplicit conversion rule that requires const T behavior (which is also\nnot desirable). There is a patch in flashinfer to fx this issue.\n\nThis PR is a temp workaround so 0.1.19 release won\u0027t block flashinfer.\nWe can reland this in next release as flashinfer\u0027s change gets into a\nrelease."
    },
    {
      "commit": "35cbc3274cf4b02d8d2e34d2510be5b34d0046ea",
      "tree": "31f94968709e408b5a0943f54f3111713fc69822",
      "parents": [
        "c1af3b337645bed13f573560910dee2743d7d3b1"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Thu Feb 19 18:10:22 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Feb 19 18:10:22 2026 -0500"
      },
      "message": "[ERROR] Complete support of CHECK macros (#465)\n\nThis PR completes the support of CHECK macros\nfor DCHECK and CHECK_EQ with error types."
    },
    {
      "commit": "c1af3b337645bed13f573560910dee2743d7d3b1",
      "tree": "50b26660729e343be7b5fb9bef062b5d8b7264f1",
      "parents": [
        "5a6b211612c4f0360f49a7a17a809d80460f557d"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Thu Feb 19 11:50:02 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Feb 19 11:50:02 2026 -0500"
      },
      "message": "[FEAT] Introduce mutable Dict  (#463)\n\nThis PR introduces Dict which serves as a mutable\nvariant of the map data structure.\n\nOverall Dict shares the same base class that backs map(immutable),\nenabling possible future possibility of freeze a dict to immutable map."
    },
    {
      "commit": "5a6b211612c4f0360f49a7a17a809d80460f557d",
      "tree": "18e72baa21f83741abccbb0772b100c3dab4a748",
      "parents": [
        "b648c5d6b7981350c165096efbb98d00787e2900"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Wed Feb 18 13:36:25 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 18 13:36:25 2026 -0500"
      },
      "message": "[REACTOR] Cleanup and improve map array containers (#462)\n\nThis PR runs the following refactor of the map and array containers.\n\n- Remove InplaceArrayBase since it is not as useful\n- Extract MapObj into map_base.h so it can be used for other different\nsubclass and variant of map if needed.\n- Add extra helper methods such as clean\n\nWe also reorganized SmallBaseMapObj after DenseMapObj as SmallBaseMapObj\nis a specialization, which can help possible future refactors to make\nSmallBaseMapObj be aware of DenseMapObj.\n\nThe split out of map_base.h is roughly manual copy and a few extra\nmanual edits to reduce unexpected surprises."
    },
    {
      "commit": "b648c5d6b7981350c165096efbb98d00787e2900",
      "tree": "af9d6b0340dc7ae3ccc332fb96af972c2fb8463e",
      "parents": [
        "65b5e90576185cb6300f43bc1307158dc99afb54"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Wed Feb 18 10:31:07 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 18 13:31:07 2026 -0500"
      },
      "message": "feat: add DFS-based ffi.ReprPrint for unified object repr (#454)\n\n## Summary\n\n- Single C++ `ffi.ReprPrint` function produces human-readable repr for\nany TVM FFI value\n- DFS with 3-state tracking (NotVisited/InProgress/Done):\n  - **DAGs**: memoized repr returned in full on every re-encounter\n  - **Cycles**: detected via InProgress state, shown as `...`\n- Addresses hidden by default; set `TVM_FFI_REPR_WITH_ADDR\u003d1` to show\n- Per-field `Repr(false)` InfoTrait to exclude fields from repr output\n- Built-in repr for String, Bytes, Tensor, Shape, Array, List, Map\n- All Python `__repr__` methods delegate to this function\n\n## Format Examples\n\n```\n42                                    # int\n\"hello\"                               # String\n(1, 2, 3)                             # Array\n[1, 2, 3]                             # List\n{\"key\": \"value\"}                      # Map\ntesting.MyObj(x\u003d1, y\u003d\"hi\")            # User object\n...                                   # Cycle marker\nfloat32[3, 4]@cpu:0@0x1234            # Tensor\n```\n\n## Test plan\n\n- [x] 55 Python tests covering primitives, containers, user objects,\nDAGs, cycles, and `TVM_FFI_REPR_WITH_ADDR`\n- [x] All pre-commit hooks pass (ruff, ty, clang-format, markdownlint,\netc.)\n- [x] Container tests (`test_container.py`) pass with updated Array\nformat"
    },
    {
      "commit": "65b5e90576185cb6300f43bc1307158dc99afb54",
      "tree": "52c24120b4da1d1a25f0151e3b0c32ce6298d89d",
      "parents": [
        "3b26a09a1e47a55e641f2267317c97114b27ab36"
      ],
      "author": {
        "name": "DarkSharpness",
        "email": "76582120+DarkSharpness@users.noreply.github.com",
        "time": "Thu Feb 19 01:54:32 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 18 12:54:32 2026 -0500"
      },
      "message": "[Feature] Support AMD HIP for cpp extension (#460)\n\nRelated issue #458 .\n\nI\u0027m not familiar with AMD at all, and most of the code is generated by\nclaude code. I\u0027ve only cleaned up a little and tried the following\nexample on one AMD machine. Need some reviews from AMD experts.\n\n```python\nimport torch\nfrom tvm_ffi import Module\nimport tvm_ffi.cpp\n\n# define the cpp source code\ncpp_source \u003d \u0027\u0027\u0027\n#include \u003chip/hip_runtime.h\u003e\n\n__global__ void add_one_kernel(const float* __restrict__ x,\n                               float* __restrict__ y,\n                               int64_t n) {\n    int64_t i \u003d (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n    if (i \u003c n) y[i] \u003d x[i] + 1.0f;\n}\n\nvoid add_one_hip(tvm::ffi::TensorView x, tvm::ffi::TensorView y) {\n    int64_t n \u003d x.size(0);\n    const float* x_ptr \u003d static_cast\u003cconst float*\u003e(x.data_ptr());\n    float* y_ptr \u003d static_cast\u003cfloat*\u003e(y.data_ptr());\n    constexpr int threads \u003d 256;\n    int blocks \u003d (int)((n + threads - 1) / threads);\n    hipStream_t stream \u003d 0;  // default stream; replace if your runtime provides a stream\n    hipLaunchKernelGGL(add_one_kernel,\n                       dim3(blocks), dim3(threads),\n                       0, stream,\n                       x_ptr, y_ptr, n);\n}\n\u0027\u0027\u0027\n\n# compile the cpp source code and load the module\nmod: Module \u003d tvm_ffi.cpp.load_inline(\n    name\u003d\"hello\",\n    cuda_sources\u003dcpp_source,\n    functions\u003d\"add_one_hip\",\n)\n\n# use the function from the loaded module to perform\nx \u003d torch.tensor([1, 2, 3, 4, 5], dtype\u003dtorch.float32, device\u003d\"cuda\")\ny \u003d torch.empty_like(x, device\u003d\"cuda\")\nmod.add_one_hip(x, y)\ntorch.testing.assert_close(x + 1, y)\n```\n\n---------\n\nCo-authored-by: gemini-code-assist[bot] \u003c176961590+gemini-code-assist[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "3b26a09a1e47a55e641f2267317c97114b27ab36",
      "tree": "4134f012b6f8ad1507cc6c2dfe717311eacd46b6",
      "parents": [
        "6adc8df7d2180ea14e463d3beeaa3d7eecb6f897"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Tue Feb 17 07:04:43 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Feb 17 10:04:43 2026 -0500"
      },
      "message": "doc: Properly document `field_static_type_index` and add more tests (#456)\n\n## Summary\n\nRestore full usage of `field_static_type_index` in TVMFFIFieldInfo with\nthorough documentation explaining its compile-time static type\nsemantics:\nthe field reflects the declared type at compile time, which may differ\nfrom the runtime type (e.g., `Any` vs `int`, `Array\u003cAny\u003e` vs\n`Array\u003cint\u003e`).\n\nThe serializer uses this field to inline POD values (None, Bool, Int,\nFloat, DataType) directly, avoiding unnecessary node-graph overhead,\nwhile routing other types through the standard node graph.\n\nChanges:\n- Add comprehensive documentation to `field_static_type_index` in\n  TVMFFIFieldInfo (C API) explaining all possible values and semantics\n- Restore `TypeToFieldStaticTypeIndex` and `TypeToRuntimeTypeIndex`\n  templates in type_traits.h\n- Restore `field_static_type_index` in all TypeTraits specializations\n- Restore POD field inlining in serialization/deserialization\n- Add comprehensive C++ and Python serialization tests (40 + 58 tests)\n\n## Test plan\n\n- [x] All 302 C++ tests pass (including 40 serialization + 21 reflection\ntests)\n- [x] All 58 Python serialization tests pass\n- [x] Verified `field_static_type_index` is populated correctly in\nreflection via test object field info"
    },
    {
      "commit": "6adc8df7d2180ea14e463d3beeaa3d7eecb6f897",
      "tree": "bc01c1ccc822009e91835ae4f03838366cebddfa",
      "parents": [
        "4f91e9cbf3126c46bdaa24f3178aaef59ffaa62f"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Mon Feb 16 21:08:20 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Feb 16 21:08:20 2026 -0500"
      },
      "message": "[EXTRA] Introduce StructuralKey (#453)\n\nThis PR introduces StructuralKey as a convenient wrapper class to\nindicate use of structural equal/hash in comparisons. It can be useful\nto serve as an intermediate wrapper class in structural equality related\nchecks."
    },
    {
      "commit": "4f91e9cbf3126c46bdaa24f3178aaef59ffaa62f",
      "tree": "b285b9704409a865042496e28d1d07b88ab02059",
      "parents": [
        "39d9b2b400646be720e98f001353cc0d8d4b0234"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sun Feb 15 22:26:50 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Feb 15 19:26:50 2026 -0800"
      },
      "message": "[TEST] Addback missing test for init once (#452)\n\nThis PR add back missing cpptest for init once."
    },
    {
      "commit": "39d9b2b400646be720e98f001353cc0d8d4b0234",
      "tree": "2aa4cd8bbeaccabc1dae1890e46c9600c8087791",
      "parents": [
        "86c4042d66bf432a3c4a217be1eeab3568329b5b"
      ],
      "author": {
        "name": "Tianqi Chen",
        "email": "tqchen@users.noreply.github.com",
        "time": "Sun Feb 15 21:33:01 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Feb 15 21:33:01 2026 -0500"
      },
      "message": "[CORE] Enable customized AnyHash/Equal in Object Type attr (#451)\n\nThis PR enables customizable anyhash/equal by object type via type attr\ncolumn."
    },
    {
      "commit": "86c4042d66bf432a3c4a217be1eeab3568329b5b",
      "tree": "81149d93c16b06f3fb4d009d9c817cf23ced7ee6",
      "parents": [
        "5e564cdfb932af63915fbeb5a5aa30671f55ae2c"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Feb 15 04:15:57 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Feb 15 07:15:57 2026 -0500"
      },
      "message": "feat: add `ffi.GetInvalidObject` global function for MISSING singleton (#447)\n\nC++ changes:\n- Register `ffi.GetInvalidObject` global function in container.cc\n- Remove `ffi.MapGetMissingObject` in favor of the new name\n\nPython changes:\n- Initialize `MISSING` in core.pyx via `_get_global_func` after\n`Function` is registered\n- Re-export `MISSING` in container.py from core\n- Add `MISSING: Object` to core.pyi type stub\n- Update _ffi_api.py stubs and __all__\n\nTests:\n- Add `test_missing_object` verifying singleton identity across imports\nand Map.get() integration"
    },
    {
      "commit": "5e564cdfb932af63915fbeb5a5aa30671f55ae2c",
      "tree": "6e982300713972a225f2b6e52b1bdd59a2367838",
      "parents": [
        "934f2d187c7fb51ab32b9351f8e56a865241aff4"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Feb 14 18:14:35 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 14 18:14:35 2026 -0800"
      },
      "message": "feat: add `DefaultFactory` support to field reflection (#446)\n\n`DefaultValue` stores a single static default shared across all\ninstances created via reflection. For mutable defaults (Array, Map,\netc.) this causes aliasing: every object receives the same underlying\ncontainer. `DefaultFactory` fixes this by storing a callable `() -\u003e Any`\nthat is invoked each time a default is needed, producing a fresh value\nper instance—mirroring Python dataclass `default_factory`.\n\nConcrete changes:\n\n- Rename `TVMFFIFieldInfo::default_value` → `default_value_or_factory`\nto reflect that the slot now holds either a value or a factory.\n- Add `kTVMFFIFieldFlagBitMaskDefaultFromFactory` (1 \u003c\u003c 5) to\n`TVMFFIFieldFlagBitMask`.\n- Add `reflection::DefaultFactory` trait (registry.h), symmetric to\n`DefaultValue`.\n- Add `reflection::SetFieldToDefault` helper (accessor.h) that resolves\nthe default—calling the factory when the flag is set—so the three\nconsumption sites (creator.h, reflection_extra.cc, serialization.cc)\nshare one implementation.\n- Propagate the rename through Rust (`c_api.rs`) and Cython (`base.pxi`)\nbindings.\n- Add `TestObjWithFactory` + three tests exercising flag inspection,\nper-instance freshness, and explicit-value bypass."
    },
    {
      "commit": "934f2d187c7fb51ab32b9351f8e56a865241aff4",
      "tree": "9f3898b331e5de791e8824a2f03325115730439b",
      "parents": [
        "c73d61a423edf69483676f727cf272feebbe4d49"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sat Feb 14 14:34:30 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 14 14:34:30 2026 -0800"
      },
      "message": "feat: Claude Skill for TVM-FFI Development (#445)\n\n"
    },
    {
      "commit": "c73d61a423edf69483676f727cf272feebbe4d49",
      "tree": "8d769ee89080bea3a19144d8df685c9659218362",
      "parents": [
        "395db3cef62f430831eb9e927357334ed3fdfade"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 13 19:01:46 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 13 19:01:46 2026 -0800"
      },
      "message": "feat: add `__copy__`, `__deepcopy__`, and `__replace__` for FFI objects (#438)\n\n## Summary\nThis PR adds first-class copy support to TVM-FFI objects, including\nPython `copy.copy`, `copy.deepcopy`, and dataclass-style `__replace__`.\n\n## Changes\n- Adds reflection-based deep-copy runtime support in C++:\n  - new `ffi.DeepCopy` entrypoint (`src/ffi/extra/deep_copy.cc`), which\n    does memoized graph copy that preserves shared references and\n    cycles.\n    - recursive copy of `ffi.Array` / `ffi.Map`\n    - treats `Str`/`Bytes` as immutable terminal values\n- resolves fields by runtime value so `Any`/`ObjectRef` fields\ncontaining containers/objects are copied correctly\n- Auto-registers shallow-copy support for copy-constructible reflected\nobject types:\n    - introduces `__ffi_shallow_copy__` registration in `ObjectDef`\n    - exposes shallow-copy method via type attributes for generic lookup\n- Wires Python class registration to install:\n    - `__copy__`, `__deepcopy__`, and `__replace__` for supported types\n    - clear `TypeError` for non-copyable types\n- deepcopy support for container roots (`ffi.Array`, `ffi.Map`) via\n`ffi.DeepCopy`\n- Updates dataclass/c_class method attachment to use reflected callables\nconsistently and hook copy setup.\n- Adds extensive test coverage in `tests/python/test_copy.py`,\nincluding:\n    - shallow/deep copy behavior\n    - shared-reference and cycle preservation\n    - long-string deep copy edge cases\n    - `Any` and `ObjectRef` deep copy edge cases\n    - non-copyable type failures (`TestNonCopyable`)"
    },
    {
      "commit": "395db3cef62f430831eb9e927357334ed3fdfade",
      "tree": "c8bcf2050bf12d16ba2265b63ef369b0faac2d3a",
      "parents": [
        "0f45528277dd024cd0a9abdeb6dcf1b97ebf8c42"
      ],
      "author": {
        "name": "Yuhong Guo",
        "email": "yuhong.gyh@antgroup.com",
        "time": "Sat Feb 14 04:54:45 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 13 12:54:45 2026 -0800"
      },
      "message": "Add Support for NVIDIA Ampere GPUs in _get_cuda_target (#440)\n\nI\u0027m using SGLang, which relies on TVM-FFI, on a machine equipped with an\nNVIDIA A10 GPU. We encountered the following error:\n\u003cimg width\u003d\"2864\" height\u003d\"2180\" alt\u003d\"image\"\nsrc\u003d\"https://github.com/user-attachments/assets/d014ed35-7940-44b1-bf36-6950a9d6d14f\"\n/\u003e\n\nThis issue is commonly observed on NVIDIA Ampere-generation GPUs (e.g.,\nA10, A100) — see related discussion:\nhttps://github.com/sgl-project/sglang/issues/18108 ,\nhttps://github.com/sgl-project/sglang/pull/18496 ,\nhttps://github.com/apache/tvm-ffi/issues/430.\n\nThe root cause is that older NVIDIA drivers (commonly deployed on Ampere\nsystems) do not support the compute_cap query field in nvidia-smi. As a\nresult, _get_cuda_target fails when trying to auto-detect the CUDA\ncompute capability.\n\n\u003cimg width\u003d\"862\" height\u003d\"66\" alt\u003d\"image\"\nsrc\u003d\"https://github.com/user-attachments/assets/66af252d-baeb-48f7-af1a-539e27d62899\"\n/\u003e\nTo address this, we fall back to querying the GPU name via:\n\n```bash\nnvidia-smi --query-gpu\u003dname --format\u003dcsv,noheader\n```\n\n\n\u003cimg width\u003d\"728\" height\u003d\"96\" alt\u003d\"image\"\nsrc\u003d\"https://github.com/user-attachments/assets/102c58f4-69ba-4649-ad06-17faaf686699\"\n/\u003e\n\nand then map known Ampere GPU names (e.g., \"NVIDIA A10\") to their\ncorresponding compute capabilities (e.g., 8.6).\n\nThis change enables robust GPU detection on Ampere devices with legacy\ndrivers while maintaining backward compatibility.\n\n---------\n\nCo-authored-by: gemini-code-assist[bot] \u003c176961590+gemini-code-assist[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "0f45528277dd024cd0a9abdeb6dcf1b97ebf8c42",
      "tree": "e0b63a1757c78103fb95b6813ffe38790d98bee7",
      "parents": [
        "9513c2f8a57f64ad7473d7cd06084719f6d5e70e"
      ],
      "author": {
        "name": "Yichen Yan",
        "email": "wenji.yyc@alibaba-inc.com",
        "time": "Sat Feb 14 04:36:52 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 13 12:36:52 2026 -0800"
      },
      "message": "fix: Suppress GCC warning for array bounds in String class (#439)\n\n```\n  In file included from /project/3rdparty/tvm/3rdparty/tvm-ffi/include/tvm/ffi/any.h:27,\n                   from /project/3rdparty/tvm/3rdparty/tvm-ffi/include/tvm/ffi/reflection/registry.h:26,\n                   from /project/3rdparty/tvm/src/relax/transform/meta_schedule.cc:24:\n  In static member function ‘static tvm::ffi::String tvm::ffi::String::Concat(const char*, size_t, const char*, size_t)’,\n      inlined from ‘tvm::ffi::String tvm::ffi::operator+(const String\u0026, const char*)’ at /project/3rdparty/tvm/3rdparty/tvm-ffi/include/tvm/ffi/string.h:972:60,\n      inlined from ‘tvm::relax::transform::MetaScheduleApplyDatabase(tvm::ffi::Optional\u003ctvm::ffi::String\u003e, bool)::\u003clambda(tvm::IRModule, tvm::relax::transform::PassContext)\u003e’ at /project/3rdparty/tvm/src/relax/transform/meta_schedule.cc:90:54:\n  /project/3rdparty/tvm/3rdparty/tvm-ffi/include/tvm/ffi/string.h:669:16: warning: ‘void* memcpy(void*, const void*, size_t)’ offset [-15, -8] is out of the bounds [0, 16] of object ‘path_workload’ with type ‘tvm::ffi::String’ [-Warray-bounds\u003d]\n    669 |     std::memcpy(dest_data + lhs_size, rhs, rhs_size);\n        |     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  /project/3rdparty/tvm/src/relax/transform/meta_schedule.cc: In function ‘tvm::relax::transform::MetaScheduleApplyDatabase(tvm::ffi::Optional\u003ctvm::ffi::String\u003e, bool)::\u003clambda(tvm::IRModule, tvm::relax::transform::PassContext)\u003e’:\n  /project/3rdparty/tvm/src/relax/transform/meta_schedule.cc:90:19: note: ‘path_workload’ declared here\n     90 |       ffi::String path_workload \u003d work_dir.value() + \"/database_workload.json\";\n        |                   ^~~~~~~~~~~~~\n```"
    },
    {
      "commit": "9513c2f8a57f64ad7473d7cd06084719f6d5e70e",
      "tree": "f71d02bcd50fcc5c99d26b1c06e5255dbe4e27f4",
      "parents": [
        "d3b5532fe68ad0d76dd8e8636a000629a7ec4716"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Fri Feb 13 12:36:34 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Feb 13 12:36:34 2026 -0800"
      },
      "message": "feat: Introduce List as Mutable Sequence (#443)\n\n## Summary\n\n- Introduces `List\u003cT\u003e`, a mutable sequence container alongside the\nexisting immutable `Array\u003cT\u003e`, with full C++ and Python support\n- Extracts `SeqBaseObj` as a shared base class for `ArrayObj` and\n`ListObj`, consolidating type-erased sequence operations (iteration,\nelement access, reverse, etc.)\n- Refactors `ArrayObj` to inherit from `SeqBaseObj`, significantly\nreducing code duplication while preserving copy-on-write semantics\n- Adds cycle detection in serialization, structural hash, structural\nequal, and JSON writer for `List` (which can form reference cycles\nunlike `Array`)\n- Updates `stl.h` so `TypeTraits\u003cstd::vector\u003cT\u003e\u003e` accepts both\n`kTVMFFIArray` and `kTVMFFIList`\n\n## Test plan\n\n- [x] C++ unit tests for `List` operations (`test_list.cc`:\nconstruction, push_back, pop_back, insert, erase, resize, Set, clear,\niterator, reverse, COW-free mutation)\n- [x] C++ tests for `List` structural equal/hash\n(`test_structural_equal_hash.cc`: List equality, List-vs-Array type\nmismatch)\n- [x] C++ tests for `List` serialization (`test_serialization.cc`:\nempty/single-element list, round-trip, cycle detection)\n- [x] Python tests for `List` (`test_container.py`: construction,\nindexing, slicing, append, insert, pop, extend, `__delitem__`,\n`__setitem__`, `__contains__`, iteration, reverse, `len`, pickle\nround-trip)"
    },
    {
      "commit": "d3b5532fe68ad0d76dd8e8636a000629a7ec4716",
      "tree": "276bf4c89ffe98331013ab680e33798e970af5d2",
      "parents": [
        "89cb6066d1d8851e61e6201ca0782d78a4ed8160"
      ],
      "author": {
        "name": "Ruihang Lai",
        "email": "ruihangl@cs.cmu.edu",
        "time": "Wed Feb 11 21:07:49 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 11 18:07:49 2026 -0800"
      },
      "message": "fix: handle UTF-8 bytes correctly in JSON parser control character check (#442)\n\nCast `*cur_` to `unsigned char` before comparing against space (0x20).\nOn platforms where `char` is signed, bytes \u003e\u003d 0x80 (valid UTF-8\ncontinuation/lead bytes) were misinterpreted as negative values, causing\nall non-ASCII strings to be rejected as \"Invalid control character\"."
    },
    {
      "commit": "89cb6066d1d8851e61e6201ca0782d78a4ed8160",
      "tree": "3d3e45d2ec4d6a2223b87d3a87b87b5c5c1c4065",
      "parents": [
        "e08dd6839a10d77d05ddef649840bcea99659d2f"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Wed Feb 11 17:58:14 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 11 20:58:14 2026 -0500"
      },
      "message": "fix(build): Broken Wheel Testing (#444)\n\nWheel testing has been broken by\nhttps://github.com/apache/tvm-ffi/pull/441, which moves `test` from\noptional-dependency to dependency-group. This PR fixes this bug."
    },
    {
      "commit": "e08dd6839a10d77d05ddef649840bcea99659d2f",
      "tree": "8116f55d2ee7e59fab7f49d943001c3213db0fdb",
      "parents": [
        "731955b304d0f4445b981e4bb9417e49209c6c37"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Wed Feb 11 16:35:16 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Feb 11 16:35:16 2026 -0800"
      },
      "message": "chore: Run ty in dev environment (#441)\n\n"
    },
    {
      "commit": "731955b304d0f4445b981e4bb9417e49209c6c37",
      "tree": "e465d81684030ad3f02313b737b96ac96ca626bd",
      "parents": [
        "245bd0d2512ca164eb57b1c18da12245981a9b17"
      ],
      "author": {
        "name": "Jinjie Liu",
        "email": "sgjzfzzf@gmail.com",
        "time": "Tue Feb 10 03:29:37 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Feb 09 14:29:37 2026 -0500"
      },
      "message": "refactor: Get `compiled_kernel` from Triton Call Directly (#423)\n\nTriton call will return the `CompiledKernel` directly to get the cubin.\nThe previous code searches the cubin by cache, which is unnecessary and\nnot robust.\n\nThis PR refactors that by taking compiled_kernel directly from the\nTriton kernel call.\n\nSigned-off-by: Jinjie Liu \u003cjjliu@baai.ac.cn\u003e"
    },
    {
      "commit": "245bd0d2512ca164eb57b1c18da12245981a9b17",
      "tree": "a4cd28ed7c1f3a665f3d3a57cb2b9eaeb4a91f28",
      "parents": [
        "90162ddc42c81bbe2913ada3fe1734d4805f741e"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Feb 08 14:04:43 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Feb 08 14:04:43 2026 -0800"
      },
      "message": "doc: More Developer Manuals (#437)\n\n"
    },
    {
      "commit": "90162ddc42c81bbe2913ada3fe1734d4805f741e",
      "tree": "a05adca7a339e9983c42b4660e466249fe472d58",
      "parents": [
        "37f45c3ed834d57de3a3513457ab239c13881272"
      ],
      "author": {
        "name": "Junru Shao",
        "email": "junrushao@apache.org",
        "time": "Sun Feb 08 04:14:19 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Feb 08 07:14:19 2026 -0500"
      },
      "message": "doc: Export Functions and Classes (#436)\n\n"
    },
    {
      "commit": "37f45c3ed834d57de3a3513457ab239c13881272",
      "tree": "38b8c064a4cc380b5909340111bc6e5a5b01a80c",
      "parents": [
        "761966953fec7e8ceba0fcc20dc003e39cf2692d"
      ],
      "author": {
        "name": "Yichen Yan",
        "email": "oraluben@outlook.com",
        "time": "Sun Feb 08 09:43:50 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Feb 07 17:43:50 2026 -0800"
      },
      "message": "Reliability update (#435)\n\nCloses #433 in a way that do not bailout when compiling in environment\nwithout torch.\n\nAlso fixes that dlpack ext\u0027s symbols does not match with torch (e.g. in\nngc container)"
    }
  ],
  "next": "761966953fec7e8ceba0fcc20dc003e39cf2692d"
}
