Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error inferring typevar on generic classes #18706

Open
alfred82santa opened this issue Feb 19, 2025 · 3 comments
Open

Error inferring typevar on generic classes #18706

alfred82santa opened this issue Feb 19, 2025 · 3 comments
Labels
bug mypy got something wrong

Comments

@alfred82santa
Copy link

Bug Report

The inferred type of methods of a generic class are not bounded to typevar value on descendant classes.

To Reproduce

from typing import Iterator, Generic, TypeVar

T = TypeVar("T", str, int)

class Parent(Generic[T]):

    @classmethod
    def method_1(cls, value: T) -> T:
        return 2*value
        
    def method_2(self, value: T) -> T:
        return 2*value
        
class ChildInt(Parent[int]):
    pass

instance = ChildInt()

reveal_type(instance.method_1)  # Revealed type is "def (value: builtins.int) -> builtins.int"
reveal_type(ChildInt.method_1)  # Revealed type is "def (value: builtins.int) -> builtins.int"

reveal_type(instance.method_2)  # Revealed type is "def (value: builtins.int) -> builtins.int"
reveal_type(ChildInt.method_2)  # Revealed type is "def (self: __main__.Parent[T`1], value: T`1) -> T`1"

https://mypy-play.net/?mypy=latest&python=3.12&gist=7ce2739ccc2b43f37187d54dcdd5f923

Expected Behavior

reveal_type(ChildInt.method_2)  # Revealed type is "def (self: __main__.ChildInt, value: builtins.int) -> builtins.int"

This soulution could be acceptable, as well:

reveal_type(ChildInt.method_2)  # Revealed type is "def (self: __main__.Parent[builtins.int], value: builtins.int) -> builtins.int"

Actual Behavior

reveal_type(ChildInt.method_2)  # Revealed type is "def (self: __main__.Parent[T`1], value: T`1) -> T`1"

Your Environment

  • Mypy version used: 1.15
  • Mypy command-line flags: no flags
  • Mypy configuration options from mypy.ini (and other config files): no config
  • Python version used: 3.13

Releated issues

#15658

@alfred82santa alfred82santa added the bug mypy got something wrong label Feb 19, 2025
@A5rocks
Copy link
Collaborator

A5rocks commented Feb 19, 2025

Does this cause any false positives or false negatives? Mypy should eventually bind self and then at that point it will find what T is. (I don't know how to interpret the related issue)

@alfred82santa
Copy link
Author

alfred82santa commented Feb 19, 2025

The related problem was that T was not bound to the type in an instance object. The current problem is that T is not bound to the type in the class object.

It could produce false negative if the class method is referenced. I know it is not common and a little bit strange.

from typing import Iterator, Generic, TypeVar, Callable, Any

T = TypeVar("T", str, int)

class Parent(Generic[T]):

    @classmethod
    def method_1(cls, value: T) -> T:
        return 2*value
        
    def method_2(self, value: T) -> T:
        return 2*value
        
class ChildInt(Parent[int]):
    pass

instance = ChildInt()

reveal_type(ChildInt.method_1)  # Revealed type is "def (value: builtins.int) -> builtins.int"
reveal_type(instance.method_1)  # Revealed type is "def (value: builtins.int) -> builtins.int"

reveal_type(ChildInt.method_2)  # Revealed type is "def (self: __main__.Parent[T`1], value: T`1) -> T`1"
reveal_type(instance.method_2)  # Revealed type is "def (value: builtins.int) -> builtins.int"

def decorator[S](f: Callable[[S, int], int]) -> Callable[[S, int], int]:
    return f
    
    
class GrandChildInt(ChildInt):
    
    method_3 = decorator(ChildInt.method_2)  # error: Argument 1 to "decorator" has incompatible type "Callable[[Parent[T], T], T]"; expected "Callable[[Parent[T], int], int]"  [arg-type]

https://mypy-play.net/?mypy=latest&python=3.12&gist=7ce2739ccc2b43f37187d54dcdd5f923

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

2 participants