python / python/mypy

super() is analyzed differently from super(C, self) in generic subclass context

Open
#13,039 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-inheritance topic-type-variables
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.