python / python/mypy

Args with a generic type will use the mother type, rather than a literal

Open
#17,090 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-join-v-union
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report
Args with a generic type will use the mother type, rather than a literal

I noticed this issue while trying to chain together two lists with different types with itertools.chain.

To Reproduce

from typing import TypeVar

T = TypeVar('T')

class M:
    pass


class C1(M):
    def my_method(self) -> None:
        pass

class C2(M):
    def my_method(self) -> None:
        pass


def test(*args: T) -> T:
    return args[0]

result = test(C1(), C2())
result.my_method()

https://mypy-play.net/?mypy=latest&python=3.12&flags=strict&gist=d78c6875b87a3040126e1926b8f7ba0c

Expected Behavior
I expected to be able to run my_method, as all arguments have it defined. Instead the mother type is used. This issue can be mitigated by extracting the arguments, giving them a literal type, then unpack them into the function:

my_args: list[C1 | C2] = [C1(), C2()]
test(*my_args)

Actual Behavior

main.py:26: error: "M" has no attribute "my_method"  [attr-defined]

I believe this happens because untyped lists defined with items will use the mother type of all items. I don't think this is very intuitive for args.

Visual Studio Code's Pylance does not give an error in this situation, even with the strict flag.

Your Environment

  • Mypy version used: 1.9.0
  • Mypy command-line flags: no flags
  • Mypy configuration options from mypy.ini (and other config files): no config
  • Python version used: 3.9, 3.10, 3.11, 3.12

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 supplied mypy-play reproduction with the reported Python and mypy versions, then trace generic argument inference for the test(*args: T) -> T example. Done means the mixed C1 and C2 call is inferred to a type exposing my_method without requiring the intermediate annotated list, with regression coverage for this behavior.

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
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.