This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vstinner
Recipients WildCard65, ZackerySpytz, corona10, hroncok, nascheme, petdance, ronaldoussoren, serhiy.storchaka, shihai1991, steve.dower, vstinner
Date 2020-11-19.10:58:55
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
> And breezy:
> (not yet reported upstream)

Oh, I didn't notice that this project is broken by the Py_REFCNT() change. I expected it to be broken by the Py_TYPE() change as others.

Should we revert the Py_REFCNT() change as well? So far, breezy is the only impacted project, and the fix should be simple, no?

breezy uses "Py_REFCNT(self) -= 1;" instead of "Py_DECREF(self);" in its StaticTuple_Intern() function:

static StaticTuple *
StaticTuple_Intern(StaticTuple *self)
    PyObject *canonical_tuple = NULL;

    if (_interned_tuples == NULL || _StaticTuple_is_interned(self)) {
        return self;
    /* SimpleSet_Add returns whatever object is present at self
     * or the new object if it needs to add it.
    canonical_tuple = SimpleSet_Add(_interned_tuples, (PyObject *)self);
    if (!canonical_tuple) {
        // Some sort of exception, propogate it.
        return NULL;
    if (canonical_tuple != (PyObject *)self) {
        // There was already a tuple with that value
        return (StaticTuple *)canonical_tuple;
    self->flags |= STATIC_TUPLE_INTERNED_FLAG;
    // The two references in the dict do not count, so that the StaticTuple
    // object does not become immortal just because it was interned.
    Py_REFCNT(self) -= 1;
    return self;

But it also uses "Py_REFCNT(self) = 2;" to "revive dead object temporarily for Discard".

static void
StaticTuple_dealloc(StaticTuple *self)
    int i, len;

    if (_StaticTuple_is_interned(self)) {
        /* revive dead object temporarily for Discard */
        Py_REFCNT(self) = 2;
        if (SimpleSet_Discard(_interned_tuples, (PyObject*)self) != 1)
            Py_FatalError("deletion of interned StaticTuple failed");
        self->flags &= ~STATIC_TUPLE_INTERNED_FLAG;
    len = self->size;
    for (i = 0; i < len; ++i) {
    Py_TYPE(self)->tp_free((PyObject *)self);

It sounds like an optimization using a set of "interned" tuples. Maybe to reduce the memory footprint.
Date User Action Args
2020-11-19 10:58:56vstinnersetrecipients: + vstinner, nascheme, ronaldoussoren, serhiy.storchaka, steve.dower, hroncok, corona10, ZackerySpytz, WildCard65, shihai1991, petdance
2020-11-19 10:58:56vstinnersetmessageid: <>
2020-11-19 10:58:56vstinnerlinkissue39573 messages
2020-11-19 10:58:55vstinnercreate