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

Generics in self types should not be bound in different ways #14729

Closed
davidhalter opened this issue Feb 17, 2023 · 1 comment
Closed

Generics in self types should not be bound in different ways #14729

davidhalter opened this issue Feb 17, 2023 · 1 comment
Labels
bug mypy got something wrong

Comments

@davidhalter
Copy link

Bug Report

In the example below you can see that you can have a self type like self: C[Tuple[T, ...]] where T is a type variable of C. This should IMO not be allowed and raise an error. I raised this here first: python/typing#1340 and @hauntsaninja agreed with me:

I agree that this mypy behaviour seems is fragile, if not outright buggy. It would certainly be clearer to use a different type variable if you wanted a different binding.

and further comments about Pyright:

Pyright interprets this as doing something recursive, which looks more correct than what mypy does, but I'm not convinced pyright's behaviour is fully correct either.

He then goes on to write an example that would not be type safe in either mypy or pyright: python/typing#1340 (comment).

To Reproduce

Just run Mypy's test suite (the test testSelfTypeRestrictedMethodOverloadInit of check-selftype.test.

class C(Generic[T]):
    @overload
    def __init__(self: C[T], item: T, use_tuple: Literal[False]) -> None: ...
    @overload
    def __init__(self: C[Tuple[T, ...]], item: T, use_tuple: Literal[True]) -> None: ...

reveal_type(C(0, use_tuple=False))  # N: Revealed type is "lib.C[builtins.int]"
reveal_type(C(0, use_tuple=True))  # N: Revealed type is "lib.C[builtins.tuple[builtins.int, ...]]"

Expected Behavior

I feel like Mypy should just generate an error in this case, because the generics are essentially bound twice.

I feel like it's debatable in the above example if even C[T] should be used. C[Tuple[T, ...]] should however definitely not be allowed, because that kind of contradicts what T is.

However I'm not saying that generics should not be allowed in these positions. I feel like this should definitely be possible, because the type variable is bound to the function, not the class:

U = TypeVar("U")
class C(Generic[T]):
    @overload
    def __init__(self: C[U], item: U, use_tuple: Literal[False]) -> None: ...
    @overload
    def __init__(self: C[Tuple[U, ...]], item: U, use_tuple: Literal[True]) -> None: ...

Your Environment

The test is part of Mypy's test suite here and my environment should therefore not matter:

https://github.com/python/mypy/blob/master/test-data/unit/check-selftype.test#L672-L705

@ilevkivskyi
Copy link
Member

There is nothing fragile or buggy about this.

@ilevkivskyi ilevkivskyi closed this as not planned Won't fix, can't repro, duplicate, stale Jun 28, 2023
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