Skip to content

Make _array_types sentinels survive cloudpickle round-trip.#391

Merged
patrick-kidger merged 1 commit into
patrick-kidger:mainfrom
hmgaudecker:fix/sentinel-cloudpickle
May 24, 2026
Merged

Make _array_types sentinels survive cloudpickle round-trip.#391
patrick-kidger merged 1 commit into
patrick-kidger:mainfrom
hmgaudecker:fix/sentinel-cloudpickle

Conversation

@hmgaudecker

Copy link
Copy Markdown
Contributor

The three module-level object() sentinels in _array_types (_any_dtype, _anonymous_dim, _anonymous_variadic_dim) are stored on persisted jaxtyping types (cls.dtypes, cls.dims). cloudpickle serialises them by value, so on the receiving side they are fresh object() instances that no longer match the live module-global sentinel — breaking is-checks that downstream shape-check code relies on. The symptom for _anonymous_variadic_dim is an AssertionError in _check_dims; the other two sentinels fail similarly when isinstance() runs against a cloudpickled type.

Replace each with a __reduce__-backed singleton class. The fourth object() sentinel in this file, _not_made, is transient factory output filtered before any type is built, so it doesn't suffer the same bug and is left alone.

Three regression tests added in test_serialisation.py, one per sentinel, each round-tripping under both pickle and cloudpickle and asserting isinstance after the round-trip — the call path that actually trips the bug under cloudpickle.

Bumps version 0.3.9 -> 0.3.10.

Fixes #390.

The three module-level `object()` sentinels in `_array_types`
(`_any_dtype`, `_anonymous_dim`, `_anonymous_variadic_dim`) are stored
on persisted jaxtyping types (`cls.dtypes`, `cls.dims`). cloudpickle
serialises them by value, so on the receiving side they are fresh
`object()` instances that no longer match the live module-global
sentinel — breaking `is`-checks that downstream shape-check code
relies on. The symptom for `_anonymous_variadic_dim` is an
`AssertionError` in `_check_dims`; the other two sentinels fail
similarly when isinstance() runs against a cloudpickled type.

Replace each with a `__reduce__`-backed singleton class. The
fourth `object()` sentinel in this file, `_not_made`, is transient
factory output filtered before any type is built, so it doesn't
suffer the same bug and is left alone.

Three regression tests added in `test_serialisation.py`, one per
sentinel, each round-tripping under both `pickle` and `cloudpickle`
and asserting `isinstance` after the round-trip — the call path
that actually trips the bug under `cloudpickle`.

Bumps version 0.3.9 -> 0.3.10.

Fixes patrick-kidger#390.
@patrick-kidger patrick-kidger merged commit fca7077 into patrick-kidger:main May 24, 2026
2 checks passed
@patrick-kidger

Copy link
Copy Markdown
Owner

Thank you for the PR! Merged 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cloudpickle round-trip of Foo[Array, "..."] breaks the anonymous-variadic-dim sentinel

2 participants