Repository: numpy/numpy
File: numpy/_core/src/multiarray/item_selection.c (C)

Code before:
            /*
             * we need to make sure and get a copy
             * so the input array is not changed
             * before the error is called
             */
            flags |= NPY_ARRAY_ENSURECOPY;
        }
        Py_INCREF(dtype);
        if (!PyArray_EquivTypes(dtype, PyArray_DESCR(out))) {
            obj = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(out),
                                                        dtype,
                                                        multi->nd,
                                                        multi->dimensions,
                                                        NULL, NULL, 0,
                                                        (PyObject *)out);
            is_newarr = 1;
        }
        else {
            obj = (PyArrayObject *)PyArray_FromArray(out, dtype, flags);
        }
    }

    if (obj == NULL) {
        goto fail;
    }
    elsize = dtype->elsize;
    ret_data = PyArray_DATA(obj);
    npy_intp transfer_strides[2] = {elsize, elsize};
    npy_intp one = 1;
    NPY_ARRAYMETHOD_FLAGS transfer_flags = 0;
    if (PyDataType_REFCHK(dtype)) {
        int is_aligned = IsUintAligned(obj);
        PyArray_GetDTypeTransferFunction(
                    is_aligned,
                    dtype->elsize,
                    dtype->elsize,
                    dtype,
                    dtype, 0, &cast_info,
                    &transfer_flags);
    }

    while (PyArray_MultiIter_NOTDONE(multi)) {
        mi = *((npy_intp *)PyArray_MultiIter_DATA(multi, n));
        if (mi < 0 || mi >= n) {
            switch(clipmode) {
            case NPY_RAISE:
                PyErr_SetString(PyExc_ValueError,
                        "invalid entry in choice "\
                        "array");
                goto fail;
            case NPY_WRAP:

Review comment (bug):
Can't comment lower, but we should adjust the `PyArray_GetDTypeTransferFunction` to use `PyArray_DESCR(obj)` for the second dtype.

There is a subtle thing that i.e. `StringDType` can be equivalent but _not_ identical (which is totally fine!).
(I.e. this code _should_ currently lead to crashes if used on the new `StringDType`, I believe.  New tests for that would be awesome, but I am happy to overlook that.)

Code after:
             * we need to make sure and get a copy
             * so the input array is not changed
             * before the error is called
             */
            copy_existing_out = 1;
        }

        if (!PyArray_EquivTypes(dtype, PyArray_DESCR(out))) {
            copy_existing_out = 1;
        }

        if (copy_existing_out) {
            Py_INCREF(dtype);
            obj = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
                                                        dtype,
                                                        multi->nd,
                                                        multi->dimensions,
                                                        NULL, NULL, 0,
                                                        (PyObject *)out);
        }
        else {
            obj = (PyArrayObject *)Py_NewRef(out);
        }
    }

    if (obj == NULL) {
        goto fail;
    }
    elsize = dtype->elsize;
    ret_data = PyArray_DATA(obj);
    npy_intp transfer_strides[2] = {elsize, elsize};
    npy_intp one = 1;
    NPY_ARRAYMETHOD_FLAGS transfer_flags = 0;
    if (PyDataType_REFCHK(dtype)) {
        int is_aligned = IsUintAligned(obj);
        PyArray_Descr *obj_dtype = PyArray_DESCR(obj);
        PyArray_GetDTypeTransferFunction(
                    is_aligned,
                    dtype->elsize,
                    obj_dtype->elsize,
                    dtype,
                    obj_dtype, 0, &cast_info,
                    &transfer_flags);
    }

    while (PyArray_MultiIter_NOTDONE(multi)) {
        mi = *((npy_intp *)PyArray_MultiIter_DATA(multi, n));
        if (mi < 0 || mi >= n) {
            switch(clipmode) {
            case NPY_RAISE:
                PyErr_SetString(PyExc_ValueError,