diff --git a/numpy/_core/src/multiarray/mapping.c b/numpy/_core/src/multiarray/mapping.c index b69fa9139957..0ae63549b60b 100644 --- a/numpy/_core/src/multiarray/mapping.c +++ b/numpy/_core/src/multiarray/mapping.c @@ -1668,7 +1668,7 @@ array_subscript(PyArrayObject *self, PyObject *op) if (PyArray_GetDTypeTransferFunction(1, itemsize, itemsize, - PyArray_DESCR(self), PyArray_DESCR(self), + PyArray_DESCR(self), PyArray_DESCR(mit->extra_op), 0, &cast_info, &transfer_flags) != NPY_SUCCEED) { goto finish; } @@ -2035,7 +2035,6 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op) goto fail; } - int allocated_array = 0; if (tmp_arr == NULL) { /* Fill extra op, need to swap first */ tmp_arr = mit->extra_op; @@ -2049,7 +2048,11 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op) if (PyArray_CopyObject(tmp_arr, op) < 0) { goto fail; } - allocated_array = 1; + /* + * In this branch we copy directly from a newly allocated array which + * may have a new descr: + */ + descr = PyArray_DESCR(tmp_arr); } if (PyArray_MapIterCheckIndices(mit) < 0) { @@ -2097,8 +2100,7 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op) // for non-REFCHK user DTypes. See gh-27057 for the prior discussion about this. if (PyArray_GetDTypeTransferFunction( 1, itemsize, itemsize, - allocated_array ? PyArray_DESCR(mit->extra_op) : PyArray_DESCR(self), - PyArray_DESCR(self), + descr, PyArray_DESCR(self), 0, &cast_info, &transfer_flags) != NPY_SUCCEED) { goto fail; } diff --git a/numpy/_core/src/multiarray/nditer_constr.c b/numpy/_core/src/multiarray/nditer_constr.c index 427dd3d876bc..ab1a540cb283 100644 --- a/numpy/_core/src/multiarray/nditer_constr.c +++ b/numpy/_core/src/multiarray/nditer_constr.c @@ -1315,8 +1315,10 @@ npyiter_check_casting(int nop, PyArrayObject **op, printf("\n"); #endif /* If the types aren't equivalent, a cast is necessary */ - if (op[iop] != NULL && !PyArray_EquivTypes(PyArray_DESCR(op[iop]), - op_dtype[iop])) { + npy_intp view_offset = NPY_MIN_INTP; + if (op[iop] != NULL && !(PyArray_SafeCast( + PyArray_DESCR(op[iop]), op_dtype[iop], &view_offset, + NPY_NO_CASTING, 1) && view_offset == 0)) { /* Check read (op -> temp) casting */ if ((op_itflags[iop] & NPY_OP_ITFLAG_READ) && !PyArray_CanCastArrayTo(op[iop], diff --git a/numpy/_core/tests/test_stringdtype.py b/numpy/_core/tests/test_stringdtype.py index 41ae1d1515ab..cdd0fecbe86c 100644 --- a/numpy/_core/tests/test_stringdtype.py +++ b/numpy/_core/tests/test_stringdtype.py @@ -495,15 +495,30 @@ def test_fancy_indexing(string_list): sarr = np.array(string_list, dtype="T") assert_array_equal(sarr, sarr[np.arange(sarr.shape[0])]) + inds = [ + [True, True], + [0, 1], + ..., + np.array([0, 1], dtype='uint8'), + ] + + lops = [ + ['a'*25, 'b'*25], + ['', ''], + ['hello', 'world'], + ['hello', 'world'*25], + ] + # see gh-27003 and gh-27053 - for ind in [[True, True], [0, 1], ...]: - for lop in [['a'*16, 'b'*16], ['', '']]: + for ind in inds: + for lop in lops: a = np.array(lop, dtype="T") - rop = ['d'*16, 'e'*16] + assert_array_equal(a[ind], a) + rop = ['d'*25, 'e'*25] for b in [rop, np.array(rop, dtype="T")]: a[ind] = b assert_array_equal(a, b) - assert a[0] == 'd'*16 + assert a[0] == 'd'*25 def test_creation_functions():