(I'm far from certain this is the correct place for this message. Maybe I should have opened a case on bpo instead?)

I got far behind on my register instruction set stuff and in the interim the ground shifted underneath me. I'm still working to try and get the test suite to pass (modulo test_ssl, which I expect to fail on Ubuntu 20.04 for the time being).

In trying to track down where my code differs from the main/3.10 branch, I was looking at the super_init_without_args() function in typeobject.c. I'm puzzled by this chunk of code near the top:

    PyObject *obj = f->f_localsplus[0];
    Py_ssize_t i, n;
    if (obj == NULL && co->co_cell2arg) {
        /* The first argument might be a cell. */
        n = PyTuple_GET_SIZE(co->co_cellvars);
        for (i = 0; i < n; i++) {
            if (co->co_cell2arg[i] == 0) {
                PyObject *cell = f->f_localsplus[co->co_nlocals + i];
                assert(PyCell_Check(cell));
                obj = PyCell_GET(cell);
                break;
            }
        }
    }


More specifically, the test for f->f_localsplus[0] being NULL seems odd. I can understand that there might not be any local variables, but there is no test for co->co_nlocals == 0. Since we don't know how many locals there might be, if there were none, wouldn't a reference to a cell variable or free variable occupy the first slot (assuming there are any)? I guess I'm confused about what the obj == NULL term in the if statement's expression is doing for us.

On a (maybe not) related note, there is a comment further down in super_init():

        /* Call super(), without args -- fill in from __class__
           and first local variable on the stack. */


I'm not seeing where the first local variable on the stack is used to fill anything in, certainly not within the block guarded by the type == NULL expression.

Skip