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

Code before:
    assert(op == cache->converted_obj);

    /* Decrease the number of dimensions to the detected ones */
    int out_ndim = PyArray_NDIM(ret);
    PyArray_Descr *out_descr = PyArray_DESCR(ret);
    if (out_ndim != ndim) {
        ((PyArrayObject_fields *)ret)->nd = ndim;
        ((PyArrayObject_fields *)ret)->descr = dtype;
    }

    int succeed = PyArray_AssignFromCache(ret, cache);

    ((PyArrayObject_fields *)ret)->nd = out_ndim;
    ((PyArrayObject_fields *)ret)->descr = out_descr;
    Py_DECREF(dtype);
    if (succeed < 0) {
        Py_DECREF(ret);
        goto fail;
    }
  success:
    NPY_END_CRITICAL_SECTION_NO_BRACKETS(array_creation_cs);
    return (PyObject *)ret;

  fail:
    NPY_END_CRITICAL_SECTION_NO_BRACKETS(array_creation_cs);
    return NULL;
}

/*
 * flags is any of
 * NPY_ARRAY_C_CONTIGUOUS (formerly CONTIGUOUS),
 * NPY_ARRAY_F_CONTIGUOUS (formerly FORTRAN),
 * NPY_ARRAY_ALIGNED,
 * NPY_ARRAY_WRITEABLE,
 * NPY_ARRAY_NOTSWAPPED,
 * NPY_ARRAY_ENSURECOPY,
 * NPY_ARRAY_WRITEBACKIFCOPY,
 * NPY_ARRAY_FORCECAST,
 * NPY_ARRAY_ENSUREARRAY,
 * NPY_ARRAY_ELEMENTSTRIDES,
 * NPY_ARRAY_ENSURENOCOPY
 *
 * or'd (|) together
 *
 * Any of these flags present means that the returned array should
 * guarantee that aspect of the array.  Otherwise the returned array
 * won't guarantee it -- it will depend on the object as to whether or
 * not it has such features.
 *
 * Note that NPY_ARRAY_ENSURECOPY is enough
 * to guarantee NPY_ARRAY_C_CONTIGUOUS, NPY_ARRAY_ALIGNED and

Review comment (bug):
Would be nice to move `Py_DECREF(dtype)` (as `XDECREF`) into the fail/success blocks (and move it down in the success one), to simplify the errors.
(Could also move a `Py_XDECREF(ret)` into the fail -- with `ret` initialized.)

Anyway, no need, just slightly improving this code (even without the change) although now we need the goto so moving cleanup into it would be good.

Code after:

    /* Decrease the number of dimensions to the detected ones */
    int out_ndim = PyArray_NDIM(ret);
    PyArray_Descr *out_descr = PyArray_DESCR(ret);
    if (out_ndim != ndim) {
        ((PyArrayObject_fields *)ret)->nd = ndim;
        ((PyArrayObject_fields *)ret)->descr = dtype;
    }

    int succeed = PyArray_AssignFromCache(ret, cache);

    ((PyArrayObject_fields *)ret)->nd = out_ndim;
    ((PyArrayObject_fields *)ret)->descr = out_descr;
    if (succeed < 0) {
        Py_CLEAR(ret);
    }

cleanup:;

    Py_XDECREF(dtype);
    Py_END_CRITICAL_SECTION();
    return (PyObject *)ret;
}

/*
 * flags is any of
 * NPY_ARRAY_C_CONTIGUOUS (formerly CONTIGUOUS),
 * NPY_ARRAY_F_CONTIGUOUS (formerly FORTRAN),
 * NPY_ARRAY_ALIGNED,
 * NPY_ARRAY_WRITEABLE,
 * NPY_ARRAY_NOTSWAPPED,
 * NPY_ARRAY_ENSURECOPY,
 * NPY_ARRAY_WRITEBACKIFCOPY,
 * NPY_ARRAY_FORCECAST,
 * NPY_ARRAY_ENSUREARRAY,
 * NPY_ARRAY_ELEMENTSTRIDES,
 * NPY_ARRAY_ENSURENOCOPY
 *
 * or'd (|) together
 *
 * Any of these flags present means that the returned array should
 * guarantee that aspect of the array.  Otherwise the returned array
 * won't guarantee it -- it will depend on the object as to whether or
 * not it has such features.
 *
 * Note that NPY_ARRAY_ENSURECOPY is enough
 * to guarantee NPY_ARRAY_C_CONTIGUOUS, NPY_ARRAY_ALIGNED and
 * NPY_ARRAY_WRITEABLE and therefore it is redundant to include
 * those as well.
 *
 * NPY_ARRAY_BEHAVED == NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE