python / python/mypy

Class factory with `type[TypeVar]` with upper bound not checked correctly (false positive)

Open
#14,790 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
Class factory, that uses TypeVar with upper bound as a type, suffers from over-inference, thinking that type[SomeTypeVar] gives its upper bound on instantiation.

To Reproduce

from typing import TypeVar, Type, Union

class A:
    def __init__(self, x: str) -> None: pass
class B:
    def __init__(self, x: int) -> None: pass
class C:
    def __init__(self, x: int) -> None: pass

T = TypeVar('T', bound=Union[A, B])

def f(x: Type[T]) -> T:
    return x(1)  \
        # E: Incompatible return value type (got "Union[A, B]", expected "T") \
        # E: Argument 1 to "A" has incompatible type "int"; expected "str"

T2 = TypeVar('T2', bound=Union[B, C])

def f2(x: Type[T2]) -> T2:
    return x(1)  # E: Incompatible return value type (got "Union[B, C]", expected "T2")

Gist

Expected Behavior

I expect only 2nd error (invalid constructor arg) to be reported, without replacing a TypeVar with Union bound.

Actual Behavior

main.py:13: error: Incompatible return value type (got "Union[A, B]", expected "T")  [return-value]
main.py:13: error: Argument 1 to "A" has incompatible type "int"; expected "str"  [arg-type]
main.py:20: error: Incompatible return value type (got "Union[B, C]", expected "T2")  [return-value]
Found 3 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.0.1 and master, repro's on older versions too
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.8-3.11 tested, irrelevant

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 provided Python reproduction and compare its diagnostics against the expected two-error result, using the linked mypy-play example if useful. Trace the type inference and constructor-checking entry points involved in type[T] with an upper-bound TypeVar; done means the invalid constructor argument remains reported without the false-positive return-value error, while existing cases still pass.

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
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.