python / python/mypy

Return type hint fails with multiple supplied type vars

Open
#14,714 2 comments 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

I'm not 100% sure how to word this but mypy fails to detect the proper return type if multiple types are supplied. It works just fine if only a single type is specified.

This scenario works just fine with pyright/pylance.

To Reproduce

import typing as t


class BaseClass:
    ...


class Sub1(BaseClass):
    ...


class Sub2(BaseClass):
    ...


ClassType = t.TypeVar("ClassType", bound=BaseClass)


def testing_union() -> t.Union[Sub1, Sub2]:
    res = sub_method(Sub1, Sub2)
    reveal_type(res)

    return res


def testing_single() -> Sub1:
    res = sub_method(Sub1)

    return res


def sub_method(*output_type: t.Type[ClassType]) -> ClassType:
    return  # type: ignore[return-value]

Expected Behavior

I expect mypy to work for both testing_union() and testing_single().

Actual Behavior

A return-value occurs in testing_union as it thinks the value is the bound base class. Using reveal_type we can see that mypy detects the type as BaseClass whereas pylance/pyright detects it as the expect3ed Sub1 | Sub2 type.

image

The output from the mypy check is

mypy-test.py:21: note: Revealed type is "mypy-test.BaseClass"
mypy-test.py:23: error: Incompatible return value type (got "BaseClass", expected "Union[Sub1, Sub2]")  [return-value]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: mypy 1.0.0 (compiled: yes)
  • Mypy command-line flags: python -m mypy file.py
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: Python 3.11.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 by running the supplied reproducer with mypy 1.0.0 and compare the revealed type for multiple versus single type arguments. Trace the type inference behavior for sub_method's variadic TypeVar arguments; done means the union case reveals Sub1 | Sub2 and passes the declared return check without weakening the single-type case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.