8000 BUG: fix refcounting for dtypemeta aliases by ngoldbaum · Pull Request #25329 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: fix refcounting for dtypemeta aliases #25329

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions numpy/_core/include/numpy/_dtype_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,5 +444,10 @@ typedef PyObject *(getitemfunction)(PyArray_Descr *, char *);
*/
#define NPY_DTYPE(descr) ((PyArray_DTypeMeta *)Py_TYPE(descr))

static inline PyArray_DTypeMeta *
NPY_DT_NewRef(PyArray_DTypeMeta *o) {
Py_INCREF(o);
return o;
}

#endif /* NUMPY_CORE_INCLUDE_NUMPY___DTYPE_API_H_ */
12 changes: 3 additions & 9 deletions numpy/_core/src/multiarray/abstractdtypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other)
if (NPY_DT_is_legacy(other) && other->type_num < NPY_NTYPES) {
if (other->type_num == NPY_BOOL) {
/* Use the default integer for bools: */
return &PyArray_IntpDType;
return NPY_DT_NewRef(&PyArray_IntpDType);
}
}
else if (NPY_DT_is_legacy(other)) {
Expand All @@ -174,7 +174,6 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other)
/* Try again with `int8`, an error may have been set, though */
PyArray_DTypeMeta *int8_dt = &PyArray_Int8DType;
res = NPY_DT_CALL_common_dtype(other, int8_dt);
Py_DECREF(int8_dt);
if (res == NULL) {
PyErr_Clear();
}
Expand All @@ -187,7 +186,6 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other)
/* And finally, we will try the default integer, just for sports... */
PyArray_DTypeMeta *default_int = &PyArray_IntpDType;
res = NPY_DT_CALL_common_dtype(other, default_int);
Py_DECREF(default_int);
if (res == NULL) {
PyErr_Clear();
}
Expand All @@ -204,7 +202,7 @@ float_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
if (NPY_DT_is_legacy(other) && other->type_num < NPY_NTYPES) {
if (other->type_num == NPY_BOOL || PyTypeNum_ISINTEGER(other->type_num)) {
/* Use the default integer for bools and ints: */
return &PyArray_DoubleDType;
return NPY_DT_NewRef(&PyArray_DoubleDType);
}
}
else if (other == &PyArray_PyIntAbstractDType) {
Expand All @@ -215,7 +213,6 @@ float_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
/* This is a back-compat fallback to usually do the right thing... */
PyArray_DTypeMeta *half_dt = &PyArray_HalfDType;
PyArray_DTypeMeta *res = NPY_DT_CALL_common_dtype(other, half_dt);
Py_DECREF(half_dt);
if (res == NULL) {
PyErr_Clear();
}
Expand All @@ -228,7 +225,6 @@ float_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
/* Retry with double (the default float) */
PyArray_DTypeMeta *double_dt = &PyArray_DoubleDType;
res = NPY_DT_CALL_common_dtype(other, double_dt);
Py_DECREF(double_dt);
return res;
}
Py_INCREF(Py_NotImplemented);
Expand All @@ -243,14 +239,13 @@ complex_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
if (other->type_num == NPY_BOOL ||
PyTypeNum_ISINTEGER(other->type_num)) {
/* Use the default integer for bools and ints: */
return &PyArray_CDoubleDType;
return NPY_DT_NewRef(&PyArray_CDoubleDType);
}
}
else if (NPY_DT_is_legacy(other)) {
/* This is a back-compat fallback to usually do the right thing... */
PyArray_DTypeMeta *cfloat_dt = &PyArray_CFloatDType;
PyArray_DTypeMeta *res = NPY_DT_CALL_common_dtype(other, cfloat_dt);
Py_DECREF(cfloat_dt);
if (res == NULL) {
PyErr_Clear();
}
Expand All @@ -263,7 +258,6 @@ complex_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
/* Retry with cdouble (the default complex) */
PyArray_DTypeMeta *cdouble_dt = &PyArray_CDoubleDType;
res = NPY_DT_CALL_common_dtype(other, cdouble_dt);
Py_DECREF(cdouble_dt);
return res;

}
Expand Down
4 changes: 0 additions & 4 deletions numpy/_core/src/multiarray/convert_datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -3049,8 +3049,6 @@ PyArray_InitializeStringCasts(void)

result = 0;
finish:
Py_DECREF(string);
Py_DECREF(unicode);
Py_XDECREF(other_dt);
return result;
}
Expand Down Expand Up @@ -3733,7 +3731,6 @@ PyArray_InitializeVoidToVoidCast(void)
};

int res = PyArray_AddCastingImplementation_FromSpec(&spec, 1);
Py_DECREF(Void);
return res;
}

Expand Down Expand Up @@ -3915,7 +3912,6 @@ PyArray_InitializeObjectToObjectCast(void)
};

int res = PyArray_AddCastingImplementation_FromSpec(&spec, 1);
Py_DECREF(Object);
return res;
}

Expand Down
4 changes: 0 additions & 4 deletions numpy/_core/src/multiarray/datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4281,10 +4281,6 @@ PyArray_InitializeDatetimeCasts()

result = 0;
fail:
Py_DECREF(datetime);
Py_DECREF(timedelta);
Py_DECREF(string);
Py_DECREF(unicode);
Py_XDECREF(tmp);
return result;
}
Expand Down
6 changes: 3 additions & 3 deletions numpy/_core/src/multiarray/dtypemeta.c
Original file line number Diff line number Diff line change
Expand Up @@ -919,13 +919,13 @@ default_builtin_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
return cls;
}
else if (cls->type_num == NPY_HALF || cls->type_num == NPY_FLOAT) {
return &PyArray_CFloatDType;
return NPY_DT_NewRef(&PyArray_CFloatDType);
}
else if (cls->type_num == NPY_DOUBLE) {
return &PyArray_CDoubleDType;
return NPY_DT_NewRef(&PyArray_CDoubleDType);
}
else if (cls->type_num == NPY_LONGDOUBLE) {
return &PyArray_CLongDoubleDType;
return NPY_DT_NewRef(&PyArray_CLongDoubleDType);
}
}
else if (other == &PyArray_PyFloatAbstractDType) {
Expand Down
4 changes: 0 additions & 4 deletions numpy/_core/src/umath/_scaled_float_dtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,6 @@ sfloat_init_casts(void)
/* Technically, it is just a copy currently so this is fine: */
spec.flags = NPY_METH_NO_FLOATINGPOINT_ERRORS;
PyArray_DTypeMeta *double_DType = &PyArray_DoubleDType;
Py_DECREF(double_DType); /* immortal anyway */
dtypes[0] = double_DType;

slots[0].slot = NPY_METH_resolve_descriptors;
Expand Down Expand Up @@ -519,7 +518,6 @@ sfloat_init_casts(void)
spec.name = "sfloat_to_bool_cast";
dtypes[0] = &PyArray_SFloatDType;
dtypes[1] = &PyArray_BoolDType;
Py_DECREF(dtypes[1]); /* immortal anyway */

if (PyArray_AddCastingImplementation_FromSpec(&spec, 0)) {
return -1;
Expand Down Expand Up @@ -762,7 +760,6 @@ sfloat_add_wrapping_loop(const char *ufunc_name, PyArray_DTypeMeta *dtypes[3])
ufunc, dtypes, wrapped_dtypes, &translate_given_descrs_to_double,
&translate_loop_descrs);
Py_DECREF(ufunc);
Py_DECREF(double_dt);

return res;
}
Expand Down Expand Up @@ -849,7 +846,6 @@ sfloat_init_ufuncs(void) {
* Add a promoter for both directions of multiply with double.
*/
PyArray_DTypeMeta *double_DType = &PyArray_DoubleDType;
Py_DECREF(double_DType); /* immortal anyway */

PyArray_DTypeMeta *promoter_dtypes[3] = {
&PyArray_SFloatDType, double_DType, NULL};
Expand Down
5 changes: 3 additions & 2 deletions numpy/_core/src/umath/dispatching.c
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ object_only_ufunc_promoter(PyUFuncObject *ufunc,
new_op_dtypes[i] = object_DType;
}
}
Py_DECREF(object_DType);

return 0;
}

Expand Down Expand Up @@ -1196,6 +1196,7 @@ logical_ufunc_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
else {
/* Always override to boolean */
item = &PyArray_BoolDType;
Py_INCREF(item);
if (op_dtypes[i] != NULL && op_dtypes[i]->type_num == NPY_OBJECT) {
force_object = 1;
}
Expand All @@ -1219,7 +1220,7 @@ logical_ufunc_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
if (signature[i] != NULL) {
continue;
}
Py_SETREF(new_op_dtypes[i], &PyArray_ObjectDType);
Py_SETREF(new_op_dtypes[i], NPY_DT_NewRef(&PyArray_ObjectDType));
}
return 0;
}
Expand Down
7 changes: 3 additions & 4 deletions numpy/_core/src/umath/special_integer_comparisons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,9 @@ pyint_comparison_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[],
PyArray_DTypeMeta *new_op_dtypes[])
{
new_op_dtypes[0] = &PyArray_ObjectDType;
new_op_dtypes[1] = &PyArray_ObjectDType;
new_op_dtypes[2] = &PyArray_BoolDType;
new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_ObjectDType);
new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_ObjectDType);
new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_BoolDType);
return 0;
}

Expand Down Expand Up @@ -468,6 +468,5 @@ init_special_int_comparisons(PyObject *umath)
finish:

Py_XDECREF(info);
Py_DECREF(Bool);
return res;
}
17 changes: 7 additions & 10 deletions numpy/_core/src/umath/string_ufuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1100,8 +1100,8 @@ string_find_rfind_count_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
new_op_dtypes[0] = op_dtypes[0];
Py_INCREF(op_dtypes[1]);
new_op_dtypes[1] = op_dtypes[1];
new_op_dtypes[2] = &PyArray_Int64DType;
new_op_dtypes[3] = &PyArray_Int64DType;
new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_Int64DType);
new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
new_op_dtypes[4] = PyArray_DTypeFromTypeNum(NPY_DEFAULT_INT);
return 0;
}
Expand All @@ -1116,9 +1116,9 @@ string_startswith_endswith_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
new_op_dtypes[0] = op_dtypes[0];
Py_INCREF(op_dtypes[1]);
new_op_dtypes[1] = op_dtypes[1];
new_op_dtypes[2] = &PyArray_Int64DType;
new_op_dtypes[3] = &PyArray_Int64DType;
new_op_dtypes[4] = &PyArray_BoolDType;
new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_Int64DType);
new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
new_op_dtypes[4] = NPY_DT_NewRef(&PyArray_BoolDType);
return 0;
}

Expand Down Expand Up @@ -1240,9 +1240,6 @@ init_comparison(PyObject *umath)

res = 0;
finish:
Py_DECREF(String);
Py_DECREF(Unicode);
Py_DECREF(Bool);
return res;
}

Expand Down Expand Up @@ -1297,10 +1294,10 @@ init_ufunc(PyObject *umath, const char *name, const char *specname, int nin, int

for (int i = 0; i < nin+nout; i++) {
if (typenums[i] == NPY_OBJECT && enc == ENCODING::UTF32) {
dtypes[i] = &PyArray_UnicodeDType;
dtypes[i] = NPY_DT_NewRef(&PyArray_UnicodeDType);
}
else if (typenums[i] == NPY_OBJECT && enc == ENCODING::ASCII) {
dtypes[i] = &PyArray_BytesDType;
dtypes[i] = NPY_DT_NewRef(&PyArray_BytesDType);
}
else {
dtypes[i] = PyArray_DTypeFromTypeNum(typenums[i]);
Expand Down
5 changes: 5 additions & 0 deletions numpy/_core/tests/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -2573,3 +2573,8 @@ def test__array_namespace__(self):
"is not supported."
):
arr.__array_namespace__(api_version="2023.12")

def test_isin_refcnt_bug(self):
# gh-25295
for _ in range(1000):
np.isclose(np.int64(2), np.int64(2), atol=1e-15, rtol=1e-300)
0