python / python/mypy

MyPy reports errors when performing nested element access using a ``TypeVar``-parameterized generic type

Open
#16,953 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

Type variables and generics enable propagating finer-grained type information through objects like containers. However, it seems that MyPy has issues when this design pattern is used in a nested manner:

To Reproduce

import typing

T = typing.TypeVar("T")

class Container(typing.Generic[T]):
    def __init__(self, value : T) -> None:
        self.value = value

class A(Container[int]):
    pass

class B(Container[A]):
    pass

def get(x: Container[T]) -> T:
    return x.value


a = B(A(5))
reveal_type(a)

b = get(a)
reveal_type(b)

c1 = get(b)
reveal_type(c1)

# This is expected to match 'c1'
c2 = get(get(a))
reveal_type(c2)

MyPy-Play link: https://gist.github.com/mypy-play/40d62fe7a0fc28bf68bd9d156ba77c5b

a.py:20: note: Revealed type is "a.B"
a.py:23: note: Revealed type is "a.A"
a.py:26: note: Revealed type is "builtins.int"
a.py:30: note: Revealed type is "builtins.int"

Reference (PyRight):

/Users/wjakob/drjit-nanobind/a.py
  /Users/wjakob/drjit-nanobind/a.py:20:13 - information: Type of "a" is "B"
  /Users/wjakob/drjit-nanobind/a.py:23:13 - information: Type of "b" is "A"
  /Users/wjakob/drjit-nanobind/a.py:26:13 - information: Type of "c1" is "int"
  /Users/wjakob/drjit-nanobind/a.py:30:13 - information: Type of "c2" is "int"

Actual Behavior

a.py:20: note: Revealed type is "a.B"
a.py:23: note: Revealed type is "a.A"
a.py:26: note: Revealed type is "builtins.int"
a.py:29: error: Argument 1 to "get" has incompatible type "B"; expected "Container[Container[int]]"  [arg-type]
a.py:30: note: Revealed type is "builtins.int"
Found 1 error in 1 file (checked 1 source file)

Your Environment
Python 3.12.2, MyPy 1.8.0

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 with the a.py reproduction from the issue, using Python 3.12.2 and MyPy 1.8.0, and compare it with the linked MyPy-Play example. Investigate nested TypeVar inference for get(get(a)). Done means the nested call produces no incompatible-argument error and c2 is revealed as builtins.int, matching c1.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.