Skip to content
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

mypyc generates code that triggers a CPython assertion #12605

Closed
godlygeek opened this issue Apr 16, 2022 · 7 comments · Fixed by #13152
Closed

mypyc generates code that triggers a CPython assertion #12605

godlygeek opened this issue Apr 16, 2022 · 7 comments · Fixed by #13152
Labels

Comments

@godlygeek
Copy link
Contributor

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
@godlygeek
Copy link
Contributor Author

This is the root cause of psf/black#2845

@godlygeek
Copy link
Contributor Author

I wonder if the assertion is checking a valid assumption, but in the wrong place: I wonder if it should be checking whether tp_call is non-null after PyType_Ready populates derived class slots, instead of before - that is, whether it should be checking this as a post-condition of PyType_Ready rather than a precondition.

@Fidget-Spinner
Copy link
Member

I'm working on this.

@hauntsaninja
Copy link
Collaborator

(off-topic) @Fidget-Spinner , while you're here, any chance you're interested in looking at what's going on with the testProtocol mypyc test failure on Python 3.11? It's currently failing with TypeError: multiple bases have instance lay-out conflict
https://github.com/python/mypy/runs/7370699638?check_suite_focus=true#step:6:167

@Fidget-Spinner
Copy link
Member

Fidget-Spinner commented Jul 16, 2022

@hauntsaninja I'm interested in fixing mypyc C API problems in 3.11. I can't promise anything though :).

@kumaraditya303
Copy link

It's currently failing with TypeError: multiple bases have instance lay-out conflict

It seems related to python/cpython#92678

@Fidget-Spinner
Copy link
Member

Thanks Kumar, that's very helpful.
I'm waiting for python/cpython#95060 to be fixed first though. Seems like some asserts in CPython are bugged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants