Extend the monoid guard to built-ins that carry a UDT fallback func - #619
Open
eriknw wants to merge 1 commit into
Open
Extend the monoid guard to built-ins that carry a UDT fallback func#619eriknw wants to merge 1 commit into
eriknw wants to merge 1 commit into
Conversation
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
from
August 5, 2026 17:44
ceeeea2 to
aaf597e
Compare
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
from
August 5, 2026 18:03
aaf597e to
8e2c61c
Compare
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
2 times, most recently
from
August 6, 2026 07:59
56e3ec8 to
eef9de4
Compare
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
from
August 6, 2026 15:39
eef9de4 to
3ddf548
Compare
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
from
August 6, 2026 15:41
3ddf548 to
95835be
Compare
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
2 times, most recently
from
August 6, 2026 20:41
37f2180 to
e43f3e9
Compare
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
from
August 7, 2026 02:49
e43f3e9 to
4430a06
Compare
The guard added with the monoid-from-built-in rejection keyed on "constructed with neither a Python func nor a numba func", which is true for most built-ins but not all of them: binary.any, first, pair, and second carry a Python orig_func as their UDT fallback while their typed ops are still TypedBuiltinBinaryOp. All four sailed past the guard and reproduced exactly what it exists to prevent: an opaque AttributeError partway through registration, with binary.<name>._monoid left pointing at the half-built monoid (binary.any.monoid is monoid.any flipped from True to False after the rejected call). binary.any is even named in the guard's own rationale as an op whose identity SuiteSparse ignores. Key the probe on the typed ops as well: any TypedBuiltinBinaryOp among them marks the op built-in. The two signals agree everywhere else, including under mapnumpy=True, where the mapped numpy binary ops hold the built-in's typed ops and no funcs, and are flagged by both tests alike; the numpy monoids themselves are mapped without passing through Monoid._build, so their registration is unaffected (verified under both mapnumpy settings). A UDF's typed ops are never TypedBuiltinBinaryOp, so nothing legitimate is newly rejected.
eriknw
force-pushed
the
38-monoid-guard-udt-fallback-builtins
branch
from
August 7, 2026 05:09
4430a06 to
a30c491
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #618. Overnight adversarial review of #617 found a hole in its guard:
_is_builtin_binaryopkeys on "no Python func and no numba func", but four built-ins (binary.any,first,pair,second) carry a Pythonorig_funcas their UDT fallback. All four sailed past the guard and reproduced exactly what #617 exists to prevent:binary.anyis even named in #617's own rationale as an op whose identity SuiteSparse ignores. This is an incomplete fix in #617 rather than a regression: the four common cases (plus/times/min/max) were already rejected cleanly.The fix keys the probe on the typed ops as well: any
TypedBuiltinBinaryOpamong them marks the op built-in. Verified that the two signals agree everywhere else, including undermapnumpy=True(where mapped numpy binary ops hold the built-in's typed ops and are flagged by both tests alike, and the numpy monoids never pass throughMonoid._build), and that a UDF's typed ops are neverTypedBuiltinBinaryOp, so nothing legitimate is newly rejected. The new test is teeth-checked: it fails with the opaque AttributeError without the fix.Gates: full pinned suite 1113 passed / 145 skipped; test_op + test_numpyops green under both mapnumpy settings; pre-commit all hooks pass.