diff options
| author | Sebastian Berg <sebastian@sipsolutions.net> | 2022-08-05 10:11:08 +0530 |
|---|---|---|
| committer | Sebastian Berg <sebastian@sipsolutions.net> | 2022-08-05 10:28:28 +0530 |
| commit | e3bcb6a7e54239ee83e0f9ca80cf71dd8f35bec9 (patch) | |
| tree | d0adbdebfce79eabce70568d551d9da47c4c1dc3 /numpy | |
| parent | f4f7595e99fffffe15effdaefe12cb7ef686ec6f (diff) | |
| download | numpy-e3bcb6a7e54239ee83e0f9ca80cf71dd8f35bec9.tar.gz | |
BUG: Replace assert with correct error
If we cache a promoted version of the loop, that promoted can mismatch
the correct one. This ends up being rejected later in the legacy paths
(should be the only path currently used), but we should reject it here
(or in principle we could reject it after cache lookup, but we are fixing
up the operation DTypes here anyway, so we are looking at the signature).
A call sequence reproducing this directly is:
np.add(1, 2, signature=(bool, int, None)) # should fail
np.add(True, 2) # A promoted loop
np.add(1, 2, signature=(bool, int, None)) # should still fail
Not that the errors differ, because the first one comes from the old
type resolution code and is currently less precise
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/core/src/umath/dispatching.c | 9 | ||||
| -rw-r--r-- | numpy/core/tests/test_ufunc.py | 9 |
2 files changed, 16 insertions, 2 deletions
diff --git a/numpy/core/src/umath/dispatching.c b/numpy/core/src/umath/dispatching.c index 5aecdd1fc..79de6c3c8 100644 --- a/numpy/core/src/umath/dispatching.c +++ b/numpy/core/src/umath/dispatching.c @@ -1016,8 +1016,13 @@ promote_and_get_ufuncimpl(PyUFuncObject *ufunc, signature[i] = (PyArray_DTypeMeta *)PyTuple_GET_ITEM(all_dtypes, i); Py_INCREF(signature[i]); } - else { - assert((PyObject *)signature[i] == PyTuple_GET_ITEM(all_dtypes, i)); + else if ((PyObject *)signature[i] != PyTuple_GET_ITEM(all_dtypes, i)) { + /* + * If signature is forced the cache may contain an incompatible + * loop found via promotion (signature not enforced). Reject it. + */ + raise_no_loop_found_error(ufunc, (PyObject **)op_dtypes); + return NULL; } } diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index e4b1ceee3..ce30e63db 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -492,6 +492,15 @@ class TestUfunc: with pytest.raises(TypeError): np.ldexp(1., np.uint64(3), signature=(None, None, "d")) + def test_partial_signature_mismatch_with_cache(self): + with pytest.raises(TypeError): + np.add(np.float16(1), np.uint64(2), sig=("e", "d", None)) + # Ensure e,d->None is in the dispatching cache (double loop) + np.add(np.float16(1), np.float64(2)) + # The error must still be raised: + with pytest.raises(TypeError): + np.add(np.float16(1), np.uint64(2), sig=("e", "d", None)) + def test_use_output_signature_for_all_arguments(self): # Test that providing only `dtype=` or `signature=(None, None, dtype)` # is sufficient if falling back to a homogeneous signature works. |
