-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Method access of generic class has Unknown rather than generic type. #6907
Comments
The current behavior is by design, so I don't consider this a bug. The expression The proper way to handle calls to a superclass class B(A[int]):
def __init__(self, x: int):
super().__init__(x) |
Thank you for the explanation. However I did not follow
What does "bind" mean here? (Clearly not the binding of a function to an instance to produce a bound method.) To my mind, the answer should follow from the runtime behavior. Accessing a regular (not def __init__(self: A[T], x: T):
... If we accept the above, then why should Pyright treat a function defined in a generic class (i.e. Regarding your suggested workaround: I did try calling Finally, the reason that I prefer to explicitly call the base class rather than use |
"Binding" occurs when a method is accessed through a class or object via a For example: Code sample in pyright playground from typing import Generic, TypeVar
T = TypeVar("T")
class A(Generic[T]):
def method(self, x: T) -> T:
...
reveal_type(A[int]().method) # "(x: int) -> int"
reveal_type(A[str]().method) # "(x: str) -> str"
reveal_type(A().method) # "(x: Unknown) -> Unknown"
reveal_type(A[int].method) # "(self: A[int], x: int) -> int"
reveal_type(A.method) # "(self: A[Unknown], x: Unknown) -> Unknown" |
For an instance method accessed through an instance, or a class method accessed through an instance or a class, I agree. But this is not true for an instance method accessed through a class. class A:
# Define an instance method.
def f(self):
...
# Access it through the class, and call it without arguments.
A.f() # TypeError: A.f() missing 1 required positional argument: 'self'
a = A()
# These 2 are equivalent.
A.f(a)
a.f() I believe this is the crux of the issue. Unlike the other 3 cases, accessing an instance method through a class via the |
It doesn't bind any of the values to any arguments, but it does bind the type of the class. From a static typing standpoint, this is important as I show in my example above. The typing spec is underspecified when it comes to binding rules. This is something I would like to see us standardize because there are differences across type checkers. I think that pyright's behavior is "more correct" than mypy's in this regard, so I will be pushing to make pyright's behavior the standard, but maybe someone can convince me otherwise. In any case, this will require a broader discussion to resolve. I don't plan to make any changes to pyright's current behavior until we reach a resolution in that discussion. |
Thank you for the explanation. I completely understand and respect your decision to keep the current behavior until a standardization is achieved. I still don't quite follow what's meant by "bind the type of the class" but I'm happy to raise this in another forum. Thanks for your work on this fantastic tool. |
Describe the bug
In strict mode, method access on a generic class (not an instance) gives a type is partially unknown error. The problem arose for me calling
__init__
of a generic superclass (example 1 below). But I found that it is not specific to__init__
- it happens with any method.I tried supply the type as an argument i.e
A[int].__init__
. This passes type checking but doesn't actually call the method at runtime.I would expect a (unbound) method to be treated similarly to a generic (non-method) function i.e. using the @ notation. My example 2 below illustrates the point.
Code or Screenshots
Example 1 - calling superclass
__init__
:(Pyright playgrround)
Example 2 - inconsistency with (non-method) generic function:
Playground
VS Code extension or command-line
Pyright playgrround, strict mode, latest version.
The text was updated successfully, but these errors were encountered: