Skip to content

mypyc generates code that triggers a CPython assertion #12605

Closed
@godlygeek

Description

@godlygeek

Crash Report

mypyc generates code that triggers a CPython assertion when a subclass inherits __call__ from a superclass.

To Reproduce

$ cat test.py
class Base:
    def __call__(self) -> None:
        return None

class Derived(Base):
    pass
$ mypyc test.py >/dev/null
$ python3-dbg -c 'import test'
../Objects/typeobject.c:5392: PyType_Ready: Assertion "type->tp_call != ((void *)0)" failed

This ends with a segfault as well, but the segfault isn't really interesting - _PyObject_ASSERT on failure makes a call to _PyObject_Dump, which calls into PyObject_Print, which fails because we're in the middle of PyType_Ready and tp_dict hasn't been created yet.

The assertion error seems to be a genuine bug, though I'm not sure whether it's a bug in CPython or in mypyc. The failing assertion is:

    if (type->tp_flags & Py_TPFLAGS_HAVE_VECTORCALL) {
        _PyObject_ASSERT((PyObject *)type, type->tp_vectorcall_offset > 0);
        _PyObject_ASSERT((PyObject *)type, type->tp_call != NULL);
    }

The second of these two assertions fails (the first succeeds). I'm not sure whether the bug is in CPython (perhaps the assertion is wrong, and it's OK to have tp_call set to NULL when Py_TPFLAGS_HAVE_VECTORCALL is set if PyType_Ready will inherit tp_call from the parent class), or whether the bug is in mypyc (perhaps it's not legal to set Py_TPFLAGS_HAVE_VECTORCALL when inheriting tp_call).

Your Environment

  • Mypy version used: mypy 0.942
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: python3.9-dbg, python3.10-dbg
  • Operating system and version: RHEL 7, Debian Bullseye

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions