8000 BUG: fix refcounting for dtypemeta aliases · numpy/numpy@6e130fa · GitHub
[go: up one dir, main page]

Skip to content

Commit 6e130fa

Browse files
committed
BUG: fix refcounting for dtypemeta aliases
1 parent bcb3463 commit 6e130fa

File tree

10 files changed

+29
-40
lines changed

10 files changed

+29
-40
lines changed

numpy/_core/include/numpy/_dtype_api.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,5 +444,10 @@ typedef PyObject *(getitemfunction)(PyArray_Descr *, char *);
444444
*/
445445
#define NPY_DTYPE(descr) ((PyArray_DTypeMeta *)Py_TYPE(descr))
446446

447+
static inline PyArray_DTypeMeta *
448+
NPY_DT_NewRef(PyArray_DTypeMeta *o) {
449+
Py_INCREF(o);
450+
return o;
451+
}
447452

448453
#endif /* NUMPY_CORE_INCLUDE_NUMPY___DTYPE_API_H_ */

numpy/_core/src/multiarray/abstractdtypes.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other)
154154
if (NPY_DT_is_legacy(other) && other->type_num < NPY_NTYPES) {
155155
if (other->type_num == NPY_BOOL) {
156156
/* Use the default integer for bools: */
157-
return &PyArray_IntpDType;
157+
return NPY_DT_NewRef(&PyArray_IntpDType);
158158
}
159159
}
160160
else if (NPY_DT_is_legacy(other)) {
@@ -174,7 +174,6 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other)
174174
/* Try again with `int8`, an error may have been set, though */
175175
PyArray_DTypeMeta *int8_dt = &PyArray_Int8DType;
176176
res = NPY_DT_CALL_common_dtype(other, int8_dt);
177-
Py_DECREF(int8_dt);
178177
if (res == NULL) {
179178
PyErr_Clear();
180179
}
@@ -187,7 +186,6 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other)
187186
/* And finally, we will try the default integer, just for sports... */
188187
PyArray_DTypeMeta *default_int = &PyArray_IntpDType;
189188
res = NPY_DT_CALL_common_dtype(other, default_int);
190-
Py_DECREF(default_int);
191189
if (res == NULL) {
192190
PyErr_Clear();
193191
}
@@ -204,7 +202,7 @@ float_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
204202
if (NPY_DT_is_legacy(other) && other->type_num < NPY_NTYPES) {
205203
if (other->type_num == NPY_BOOL || PyTypeNum_ISINTEGER(other->type_num)) {
206204
/* Use the default integer for bools and ints: */
207-
return &PyArray_DoubleDType;
205+
return NPY_DT_NewRef(&PyArray_DoubleDType);
208206
}
209207
}
210208
else if (other == &PyArray_PyIntAbstractDType) {
@@ -215,7 +213,6 @@ float_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
215213
/* This is a back-compat fallback to usually do the right thing... */
216214
PyArray_DTypeMeta *half_dt = &PyArray_HalfDType;
217215
PyArray_DTypeMeta *res = NPY_DT_CALL_common_dtype(other, half_dt);
218-
Py_DECREF(half_dt);
219216
if (res == NULL) {
220217
PyErr_Clear();
221218
}
@@ -228,7 +225,6 @@ float_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
228225
/* Retry with double (the default float) */
229226
PyArray_DTypeMeta *double_dt = &PyArray_DoubleDType;
230227
res = NPY_DT_CALL_common_dtype(other, double_dt);
231-
Py_DECREF(double_dt);
232228
return res;
233229
}
234230
Py_INCREF(Py_NotImplemented);
@@ -243,14 +239,13 @@ complex_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
243239
if (other->type_num == NPY_BOOL ||
244240
PyTypeNum_ISINTEGER(other->type_num)) {
245241
/* Use the default integer for bools and ints: */
246-
return &PyArray_CDoubleDType;
242+
return NPY_DT_NewRef(&PyArray_CDoubleDType);
247243
}
248244
}
249245
else if (NPY_DT_is_legacy(other)) {
250246
/* This is a back-compat fallback to usually do the right thing... */
251247
PyArray_DTypeMeta *cfloat_dt = &PyArray_CFloatDType;
252248
PyArray_DTypeMeta *res = NPY_DT_CALL_common_dtype(other, cfloat_dt);
253-
Py_DECREF(cfloat_dt);
254249
if (res == NULL) {
255250
PyErr_Clear();
256251
}
@@ -263,7 +258,6 @@ complex_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
263258
/* Retry with cdouble (the default complex) */
264259
PyArray_DTypeMeta *cdouble_dt = &PyArray_CDoubleDType;
265260
res = NPY_DT_CALL_common_dtype(other, cdouble_dt);
266-
Py_DECREF(cdouble_dt);
267261
return res;
268262

269263
}

numpy/_core/src/multiarray/convert_datatype.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,8 +3049,6 @@ PyArray_InitializeStringCasts(void)
30493049

30503050
result = 0;
30513051
finish:
3052-
Py_DECREF(string);
3053-
Py_DECREF(unicode);
30543052
Py_XDECREF(other_dt);
30553053
return result;
30563054
}
@@ -3733,7 +3731,6 @@ PyArray_InitializeVoidToVoidCast(void)
37333731
};
37343732

37353733
int res = PyArray_AddCastingImplementation_FromSpec(&spec, 1);
3736-
Py_DECREF(Void);
37373734
return res;
37383735
}
37393736

@@ -3915,7 +3912,6 @@ PyArray_InitializeObjectToObjectCast(void)
39153912
};
39163913

39173914
int res = PyArray_AddCastingImplementation_FromSpec(&spec, 1);
3918-
Py_DECREF(Object);
39193915
return res;
39203916
}
39213917

numpy/_core/src/multiarray/datetime.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4281,10 +4281,6 @@ PyArray_InitializeDatetimeCasts()
42814281

42824282
result = 0;
42834283
fail:
4284-
Py_DECREF(datetime);
4285-
Py_DECREF(timedelta);
4286-
Py_DECREF(string);
4287-
Py_DECREF(unicode);
42884284
Py_XDECREF(tmp);
42894285
return result;
42904286
}

numpy/_core/src/multiarray/dtypemeta.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -919,13 +919,13 @@ default_builtin_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
919919
return cls;
920920
}
921921
else if (cls->type_num == NPY_HALF || cls->type_num == NPY_FLOAT) {
922-
return &PyArray_CFloatDType;
922+
return NPY_DT_NewRef(&PyArray_CFloatDType);
923923
}
924924
else if (cls->type_num == NPY_DOUBLE) {
925-
return &PyArray_CDoubleDType;
925+
return NPY_DT_NewRef(&PyArray_CDoubleDType);
926926
}
927927
else if (cls->type_num == NPY_LONGDOUBLE) {
928-
return &PyArray_CLongDoubleDType;
928+
return NPY_DT_NewRef(&PyArray_CLongDoubleDType);
929929
}
930930
}
931931
else if (other == &PyArray_PyFloatAbstractDType) {

numpy/_core/src/umath/_scaled_float_dtype.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,6 @@ sfloat_init_casts(void)
487487
/* Technically, it is just a copy currently so this is fine: */
488488
spec.flags = NPY_METH_NO_FLOATINGPOINT_ERRORS;
489489
PyArray_DTypeMeta *double_DType = &PyArray_DoubleDType;
490-
Py_DECREF(double_DType); /* immortal anyway */
491490
dtypes[0] = double_DType;
492491

493492
slots[0].slot = NPY_METH_resolve_descriptors;
@@ -519,7 +518,6 @@ sfloat_init_casts(void)
519518
spec.name = "sfloat_to_bool_cast";
520519
dtypes[0] = &PyArray_SFloatDType;
521520
dtypes[1] = &PyArray_BoolDType;
522-
Py_DECREF(dtypes[1]); /* immortal anyway */
523521

524522
if (PyArray_AddCastingImplementation_FromSpec(&spec, 0)) {
525523
return -1;
@@ -762,7 +760,6 @@ sfloat_add_wrapping_loop(const char *ufunc_name, PyArray_DTypeMeta *dtypes[3])
762760
ufunc, dtypes, wrapped_dtypes, &translate_given_descrs_to_double,
763761
&translate_loop_descrs);
764762
Py_DECREF(ufunc);
765-
Py_DECREF(double_dt);
766763

767764
return res;
768765
}
@@ -849,7 +846,6 @@ sfloat_init_ufuncs(void) {
849846
* Add a promoter for both directions of multiply with double.
850847
*/
851848
PyArray_DTypeMeta *double_DType = &PyArray_DoubleDType;
852-
Py_DECREF(double_DType); /* immortal anyway */
853849

854850
PyArray_DTypeMeta *promoter_dtypes[3] = {
855851
&PyArray_SFloatDType, double_DType, NULL};

numpy/_core/src/umath/dispatching.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ object_only_ufunc_promoter(PyUFuncObject *ufunc,
11511151
new_op_dtypes[i] = object_DType;
11521152
}
11531153
}
1154-
Py_DECREF(object_DType);
1154+
11551155
return 0;
11561156
}
11571157

@@ -1196,6 +1196,7 @@ logical_ufunc_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
11961196
else {
11971197
/* Always override to boolean */
11981198
item = &PyArray_BoolDType;
1199+
Py_INCREF(item);
11991200
if (op_dtypes[i] != NULL && op_dtypes[i]->type_num == NPY_OBJECT) {
12001201
force_object = 1;
12011202
}
@@ -1219,7 +1220,7 @@ logical_ufunc_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
12191220
if (signature[i] != NULL) {
12201221
continue;
12211222
}
1222-
Py_SETREF(new_op_dtypes[i], &PyArray_ObjectDType);
1223+
Py_SETREF(new_op_dtypes[i], NPY_DT_NewRef(&PyArray_ObjectDType));
12231224
}
12241225
return 0;
12251226
}

numpy/_core/src/umath/special_integer_comparisons.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,9 @@ pyint_comparison_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
310310
PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[],
311311
PyArray_DTypeMeta *new_op_dtypes[])
312312
{
313-
new_op_dtypes[0] = &PyArray_ObjectDType;
314-
new_op_dtypes[1] = &PyArray_ObjectDType;
315-
new_op_dtypes[2] = &PyArray_BoolDType;
313+
new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_ObjectDType);
314+
new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_ObjectDType);
315+
new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_BoolDType);
316316
return 0;
317317
}
318318

@@ -468,6 +468,5 @@ init_special_int_comparisons(PyObject *umath)
468468
finish:
469469

470470
Py_XDECREF(info);
471-
Py_DECREF(Bool);
472471
return res;
473472
}

numpy/_core/src/umath/string_ufuncs.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,8 +1100,8 @@ string_find_rfind_count_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
11001100
new_op_dtypes[0] = op_dtypes[0];
11011101
Py_INCREF(op_dtypes[1]);
11021102
new_op_dtypes[1] = op_dtypes[1];
1103-
new_op_dtypes[2] = &PyArray_Int64DType;
1104-
new_op_dtypes[3] = &PyArray_Int64DType;
1103+
new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_Int64DType);
1104+
new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
11051105
new_op_dtypes[4] = PyArray_DTypeFromTypeNum(NPY_DEFAULT_INT);
11061106
return 0;
11071107
}
@@ -1116,9 +1116,9 @@ string_startswith_endswith_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
11161116
new_op_dtypes[0] = op_dtypes[0];
11171117
Py_INCREF(op_dtypes[1]);
11181118
new_op_dtypes[1] = op_dtypes[1];
1119-
new_op_dtypes[2] = &PyArray_Int64DType;
1120-
new_op_dtypes[3] = &PyArray_Int64DType;
1121-
new_op_dtypes[4] = &PyArray_BoolDType;
1119+
new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_Int64DType);
1120+
new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
1121+
new_op_dtypes[4] = NPY_DT_NewRef(&PyArray_BoolDType);
11221122
return 0;
11231123
}
11241124

@@ -1240,9 +1240,6 @@ init_comparison(PyObject *umath)
12401240

12411241
res = 0;
12421242
finish:
1243-
Py_DECREF(String);
1244-
Py_DECREF(Unicode);
1245-
Py_DECREF(Bool);
12461243
return res;
12471244
}
12481245

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

12981295
for (int i = 0; i < nin+nout; i++) {
12991296
if (typenums[i] == NPY_OBJECT && enc == ENCODING::UTF32) {
1300-
dtypes[i] = &PyArray_UnicodeDType;
1297+
dtypes[i] = NPY_DT_NewRef(&PyArray_UnicodeDType);
13011298
}
13021299
else if (typenums[i] == NPY_OBJECT && enc == ENCODING::ASCII) {
1303-
dtypes[i] = &PyArray_BytesDType;
1300+
dtypes[i] = NPY_DT_NewRef(&PyArray_BytesDType);
13041301
}
13051302
else {
13061303
dtypes[i] = PyArray_DTypeFromTypeNum(typenums[i]);

numpy/_core/tests/test_regression.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2573,3 +2573,8 @@ def test__array_namespace__(self):
25732573
"is not supported."
25742574
):
25752575
arr.__array_namespace__(api_version="2023.12")
2576+
2577+
def test_isin_refcnt_bug(self):
2578+
# gh-25295
2579+
for _ in range(1000):
2580+
np.isclose(np.int64(2), np.int64(2), atol=1e-15, rtol=1e-300)

0 commit comments

Comments
 (0)
0