super() is analyzed differently from super(C, self) in generic subclass context
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
Consider a minimal reproducing example, based on one from #7362
from typing import TypeVar
T = TypeVar('T', str, int)
class C(list[T]):
def pop_item(self, key: int) -> T:
reveal_type(super().pop(key))
return super().pop(key)
(https://mypy-play.net/?mypy=0.961&python=3.10&gist=ab00ab8ee474443b979cb00ea4284946)
main.py:7: note: Revealed type is "T`1"
main.py:8: error: Incompatible return value type (got "T", expected "str")
main.py:8: error: Incompatible return value type (got "T", expected "int")
This is clearly unexpected, as this should work normally. However, if instead of writing super(), we write super(C, self), which is exactly equivalent syntactically in Python 3, we get
from typing import TypeVar
T = TypeVar('T', str, int)
class C(list[T]):
def pop_item(self, key: int) -> T:
reveal_type(super(C, self).pop(key))
return super(C, self).pop(key)
(https://mypy-play.net/?mypy=0.961&python=3.10&gist=44206838005bf4acfa264a42eecb0eb5)
main.py:7: note: Revealed type is "builtins.str"
main.py:7: note: Revealed type is "builtins.int"
As expected.
Possible fix
Here, Mypy is analyzing super(), differently from super(C, self), which is syntactically incorrect. If super() would instead be (correctly) parsed as super(C, self) in this case, the problem disappears. Note that this also fixes #7362 and #10130.
I don't know enough about Mypy internals to understand why Mypy does not take super() to be equal to super(C, self) here, but perhaps this could be an easy fix?
2024 edit
This reproduces on 1.8.0 as well.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the minimal reproducing example from the issue in mypy or the linked mypy-play cases, comparing bare super() with super(C, self). Trace how each form is analyzed in the generic subclass context. Done means both forms reveal the same concrete type and the return statement passes without incompatible-type errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100